Merge pull request #4956 from sleuthkit/release-4.12.0

Merge release 4.12.0 branch into develop branch
This commit is contained in:
Richard Cordovano 2019-06-26 14:20:59 -04:00 committed by GitHub
commit e92a827ac9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
97 changed files with 3871 additions and 1520 deletions

View File

@ -89,11 +89,10 @@ import org.sleuthkit.datamodel.TskData;
public class DataContentViewerOtherCases extends JPanel implements DataContentViewer {
private static final long serialVersionUID = -1L;
private static final String UUID_PLACEHOLDER_STRING = "NoCorrelationAttributeInstance";
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 final OtherOccurrencesFilesTableModel filesTableModel;
private final OtherOccurrencesCasesTableModel casesTableModel;
private final OtherOccurrencesDataSourcesTableModel dataSourcesTableModel;
@ -129,6 +128,16 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
reset();
}
/**
* Get a placeholder string to use in place of case uuid when it isn't
* available
*
* @return UUID_PLACEHOLDER_STRING
*/
static String getPlaceholderUUID() {
return UUID_PLACEHOLDER_STRING;
}
private void customizeComponents() {
ActionListener actList = (ActionEvent e) -> {
JMenuItem jmi = (JMenuItem) e.getSource();
@ -837,7 +846,6 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
* selection
*/
private void updateOnDataSourceSelection() {
int[] selectedCaseIndexes = casesTable.getSelectedRows();
int[] selectedDataSources = dataSourcesTable.getSelectedRows();
filesTableModel.clearTable();
for (CorrelationAttributeInstance corAttr : correlationAttributes) {
@ -846,23 +854,20 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
// get correlation and reference set instances from DB
correlatedNodeDataMap.putAll(getCorrelatedInstances(corAttr, dataSourceName, deviceId));
for (OtherOccurrenceNodeInstanceData nodeData : correlatedNodeDataMap.values()) {
for (int selectedCaseRow : selectedCaseIndexes) {
for (int selectedDataSourceRow : selectedDataSources) {
try {
if (nodeData.isCentralRepoNode()) {
if (casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)) != null
&& casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(selectedCaseRow)).getCaseUUID().equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
&& dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
filesTableModel.addNodeData(nodeData);
}
} else {
if (dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
filesTableModel.addNodeData(nodeData);
}
for (int selectedDataSourceRow : selectedDataSources) {
try {
if (nodeData.isCentralRepoNode()) {
if (dataSourcesTableModel.getCaseUUIDForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID())
&& dataSourcesTableModel.getDeviceIdForRow(dataSourcesTable.convertRowIndexToModel(selectedDataSourceRow)).equals(nodeData.getDeviceID())) {
filesTableModel.addNodeData(nodeData);
}
} else {
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(), ex);
}
} catch (EamDbException ex) {
LOGGER.log(Level.WARNING, "Unable to get correlation attribute instance from OtherOccurrenceNodeInstanceData for case " + nodeData.getCaseName(), ex);
}
}
}
@ -928,7 +933,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
if (EamDb.isEnabled()) {
CorrelationCase partialCase;
partialCase = casesTableModel.getCorrelationCase(casesTable.convertRowIndexToModel(caseTableRowIdx));
if (partialCase == null){
if (partialCase == null) {
return "";
}
return EamDb.getInstance().getCaseByUUID(partialCase.getCaseUUID()).getCreationDate();
@ -1141,6 +1146,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
private final String dataSourceID;
private final String filePath;
private final String type;
private final String caseUUID;
UniquePathKey(OtherOccurrenceNodeInstanceData nodeData) {
super();
@ -1151,6 +1157,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
filePath = null;
}
type = nodeData.getType();
String tempCaseUUID;
try {
tempCaseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
} catch (EamDbException ignored) {
tempCaseUUID = UUID_PLACEHOLDER_STRING;
//place holder value will be used since correlation attribute was unavailble
}
caseUUID = tempCaseUUID;
}
@Override
@ -1159,14 +1173,15 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
UniquePathKey otherKey = (UniquePathKey) (other);
return (Objects.equals(otherKey.getDataSourceID(), this.getDataSourceID())
&& Objects.equals(otherKey.getFilePath(), this.getFilePath())
&& Objects.equals(otherKey.getType(), this.getType()));
&& Objects.equals(otherKey.getType(), this.getType())
&& Objects.equals(otherKey.getCaseUUID(), this.getCaseUUID()));
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(getDataSourceID(), getFilePath(), getType());
return Objects.hash(getDataSourceID(), getFilePath(), getType(), getCaseUUID());
}
/**
@ -1195,5 +1210,14 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi
String getDataSourceID() {
return dataSourceID;
}
/**
* Get the case uuid for the UniquePathKey
*
* @return the case UUID
*/
String getCaseUUID() {
return caseUUID;
}
}
}

View File

@ -23,6 +23,7 @@ import java.util.Objects;
import java.util.Set;
import javax.swing.table.AbstractTableModel;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
/**
* Model for cells in the data sources section of the other occurrences data
@ -86,6 +87,25 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
return ((DataSourceColumnItem) dataSourceSet.toArray()[rowIdx]).getDeviceId();
}
/**
* Get the case uuid of the case the data source shown at the specified row
* index exists in
*
* @param rowIdx the row index of the data source you want the case uuid for
*
* @return the case uuid of the case the specified data source exists in or
* an empty string if a device id could not be retrieved
*/
String getCaseUUIDForRow(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]).getCaseUUID();
}
/**
* Get the case name of the data source shown at the specified row index
*
@ -115,7 +135,15 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
* @param newNodeData data to add to the table
*/
void addNodeData(OtherOccurrenceNodeData newNodeData) {
dataSourceSet.add(new DataSourceColumnItem((OtherOccurrenceNodeInstanceData) newNodeData));
OtherOccurrenceNodeInstanceData nodeData = (OtherOccurrenceNodeInstanceData) newNodeData;
String caseUUID;
try {
caseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
} catch (EamDbException ignored) {
caseUUID = DataContentViewerOtherCases.getPlaceholderUUID();
//place holder value will be used since correlation attribute was unavailble
}
dataSourceSet.add(new DataSourceColumnItem(nodeData.getCaseName(), nodeData.getDeviceID(), nodeData.getDataSourceName(), caseUUID));
fireTableDataChanged();
}
@ -136,30 +164,23 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
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());
}
private final String caseUUID;
/**
* 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 deviceId the device id for the data source
* @param dataSourceName the name of the data source
* @param caseUUID the case uuid for the case the data source
* exists in
*/
private DataSourceColumnItem(String caseName, String deviceId, String dataSourceName) {
private DataSourceColumnItem(String caseName, String deviceId, String dataSourceName, String caseUUID) {
this.caseName = caseName;
this.deviceId = deviceId;
this.dataSourceName = dataSourceName;
this.caseUUID = caseUUID;
}
/**
@ -189,17 +210,27 @@ final class OtherOccurrencesDataSourcesTableModel extends AbstractTableModel {
return caseName;
}
/**
* Get the case uuid of the case the data source exists in
*
* @return the case UUID
*/
private String getCaseUUID() {
return caseUUID;
}
@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());
&& deviceId.equals(((DataSourceColumnItem) other).getDeviceId())
&& caseUUID.equals(((DataSourceColumnItem) other).getCaseUUID());
}
@Override
public int hashCode() {
return Objects.hash(caseName, deviceId, dataSourceName);
return Objects.hash(caseName, deviceId, dataSourceName, caseUUID);
}
}

View File

@ -25,6 +25,7 @@ import java.util.Map;
import javax.swing.table.AbstractTableModel;
import org.openide.util.NbBundle.Messages;
import org.apache.commons.io.FilenameUtils;
import org.sleuthkit.autopsy.centralrepository.datamodel.EamDbException;
/**
* Model for cells in the files section of the other occurrences data content
@ -114,7 +115,14 @@ public class OtherOccurrencesFilesTableModel extends AbstractTableModel {
}
private String createNodeKey(OtherOccurrenceNodeInstanceData nodeData) {
return nodeData.getCaseName() + nodeData.getDataSourceName() + nodeData.getDeviceID() + nodeData.getFilePath();
String caseUUID;
try {
caseUUID = nodeData.getCorrelationAttributeInstance().getCorrelationCase().getCaseUUID();
} catch (EamDbException ignored) {
caseUUID = DataContentViewerOtherCases.getPlaceholderUUID();
//place holder value will be used since correlation attribute was unavailble
}
return nodeData.getCaseName() + nodeData.getDataSourceName() + nodeData.getDeviceID() + nodeData.getFilePath() + caseUUID;
}
/**

View File

@ -72,7 +72,7 @@ final class AccountDeviceInstanceNode extends AbstractNode {
}
@Override
@NbBundle.Messages(value = {"AccountNode.device=Device", "AccountNode.accountName=Account", "AccountNode.accountType=Type", "AccountNode.messageCount=Messages"})
@NbBundle.Messages(value = {"AccountNode.device=Device", "AccountNode.accountName=Account", "AccountNode.accountType=Type", "AccountNode.messageCount=Items"})
protected Sheet createSheet() {
Sheet sheet = super.createSheet();
Sheet.Set properties = sheet.get(Sheet.PROPERTIES);

View File

@ -1,7 +1,7 @@
AccountNode.accountName=Account
AccountNode.accountType=Type
AccountNode.device=Device
AccountNode.messageCount=Messages
AccountNode.messageCount=Items
applyText=Apply
CTL_OpenCVTAction=Communications
CVTTopComponent.name=\ Communications Visualization

View File

@ -507,7 +507,9 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel {
private void bnTestDatabaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestDatabaseActionPerformed
lbTestDatabase.setIcon(null);
lbTestDatabase.paintImmediately(lbTestDatabase.getVisibleRect());
lbTestDbWarning.setText("");
lbTestDbWarning.paintImmediately(lbTestDbWarning.getVisibleRect());
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try {
CaseDbConnectionInfo info = new CaseDbConnectionInfo(
@ -530,7 +532,9 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel {
private void bnTestMessageServiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestMessageServiceActionPerformed
lbTestMessageService.setIcon(null);
lbTestMessageService.paintImmediately(lbTestMessageService.getVisibleRect());
lbTestMessageWarning.setText("");
lbTestMessageWarning.paintImmediately(lbTestMessageWarning.getVisibleRect());
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
int port;
@ -561,7 +565,9 @@ public final class MultiUserSettingsPanel extends javax.swing.JPanel {
private void bnTestSolrActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestSolrActionPerformed
lbTestSolr.setIcon(null);
lbTestSolr.paintImmediately(lbTestSolr.getVisibleRect());
lbTestSolrWarning.setText("");
lbTestSolrWarning.paintImmediately(lbTestSolrWarning.getVisibleRect());
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class);

View File

@ -43,31 +43,21 @@ ConfigVisualPanel2.jCheckBox2.text=jCheckBox2
ConfigVisualPanel2.jTextField1.text=jTextField1
ConfigVisualPanel1.jRadioButton1.text=Create new configuration
ConfigVisualPanel1.jRadioButton2.text=Open existing configuration
ConfigVisualPanel1.jLabel1.text_1=Configuration file:
ConfigVisualPanel1.configFileTextField.text_1=
ConfigVisualPanel2.modifiedDateLabel.text=Modified Within:
ConfigVisualPanel2.folderNamesLabel.text=Folder names:
ConfigVisualPanel2.finalizeImageWriter.text=Continue imaging after searches are performed
ConfigVisualPanel2.filenamesLabel.text=File names:
ConfigVisualPanel2.extensionsTextField.text=
ConfigVisualPanel2.shouldAlertCheckBox.text=Alert in imager console if rule matches
ConfigVisualPanel2.shouldSaveCheckBox.text=Extract file if it matches a rule
ConfigVisualPanel2.deleteRuleButton.text=Delete Rule
ConfigVisualPanel2.descriptionEditTextField.text=
ConfigVisualPanel2.editRuleButton.text=Edit Rule
ConfigVisualPanel2.newRuleButton.text=New Rule
ConfigVisualPanel2.ruleNameEditTextField.text=
ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text=Alert if encryption programs are found
ConfigVisualPanel2.fullPathsLabel.text=Full paths:
ConfigVisualPanel2.daysIncludedLabel.text=day(s)
ConfigVisualPanel2.daysIncludedTextField.text=
ConfigVisualPanel2.configFileTextField.toolTipText=
ConfigVisualPanel2.configFileTextField.text=
ConfigVisualPanel2.filenamesTable.columnModel.title0=
ConfigVisualPanel2.fileSizeLabel.text=File size in bytes:
ConfigVisualPanel2.extensionsLabel.text=Extensions:
ConfigVisualPanel2.descriptionLabel.text=Description:
ConfigVisualPanel2.ruleNameLabel.text=Rule Name:
ConfigVisualPanel2.ruleNameLabel.text=Rule name:
ConfigVisualPanel2.ruleSetFileLabel.text=Configuration rule file:
EditRulePanel.ruleNameLabel.text=Rule Set:
EditRulePanel.descriptionTextField.text=
@ -85,45 +75,48 @@ EditRulePanel.jTable1.columnModel.title3=Title 4
EditRulePanel.jTable1.columnModel.title2=Title 3
EditRulePanel.jTable1.columnModel.title1=Title 2
EditRulePanel.shouldAlertCheckBox.actionCommand=
EditFullPathsRulePanel.ruleNameLabel.text=Rule Name:
EditFullPathsRulePanel.descriptionLabel.text=Description:
EditFullPathsRulePanel.descriptionTextField.text=
EditFullPathsRulePanel.ruleNameLabel.text=Rule name:
EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
EditFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
EditFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
EditFullPathsRulePanel.ruleNameTextField.text=
EditFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if a path matches
EditFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a path
EditFullPathsRulePanel.fullPathsLabel.text=Full paths:
EditFullPathsRulePanel.fullPathsLabel.toolTipText=
EditNonFullPathsRulePanel.ruleNameTextField.text=
EditNonFullPathsRulePanel.ruleNameLabel.text=Rule Name:
EditNonFullPathsRulePanel.descriptionLabel.text=Description:
EditNonFullPathsRulePanel.descriptionTextField.text=
EditNonFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
EditNonFullPathsRulePanel.ruleNameLabel.text=Rule name:
EditNonFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a condition
EditNonFullPathsRulePanel.daysIncludedLabel.text=day(s)
EditNonFullPathsRulePanel.modifiedDateLabel.text=Modified Within:
EditNonFullPathsRulePanel.fileSizeLabel.text=File size (bytes):
EditNonFullPathsRulePanel.folderNamesLabel.text=Folder names:
EditNonFullPathsRulePanel.filenamesLabel.text=File names:
EditNonFullPathsRulePanel.extensionsTextField.text=
EditNonFullPathsRulePanel.extensionsLabel.text=Extensions:
EditNonFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
EditNonFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
EditNonFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if a condition matches
ConfigVisualPanel1.browseButton.text=Browse
ConfigVisualPanel2.fullPathsTable.columnModel.title0=
ConfigVisualPanel2.folderNamesTable.columnModel.title0=
ConfigVisualPanel2.shouldSaveCheckBox.toolTipText=
NewRuleSetPanel.chooseLabel.text=Choose the type of rule
EditNonFullPathsRulePanel.minSizeLabel.text=Minimum:
EditNonFullPathsRulePanel.maxSizeLabel.text=Maximum:
EditNonFullPathsRulePanel.minSizeTextField.text=
EditNonFullPathsRulePanel.maxSizeTextField.text=
ConfigVisualPanel2.maxSizeTextField.text=
ConfigVisualPanel2.maxSizeLabel.text=Maximum:
ConfigVisualPanel2.minSizeTextField.text=
ConfigVisualPanel2.minSizeLabel.text=Minimum:
EditNonFullPathsRulePanel.minDaysTextField.text=jFormattedTextField1
ConfigVisualPanel1.browseButton.toolTipText=
EditNonFullPathsRulePanel.extensionsRadioButton.text=
EditNonFullPathsRulePanel.filenamesRadioButton.text=
EditNonFullPathsRulePanel.extensionsRadioButton.toolTipText=Extensions and File names are mutually exclusive
EditNonFullPathsRulePanel.filenamesRadioButton.toolTipText=Extensions and File names are mutually exclusive
EditNonFullPathsRulePanel.userFolderNote.text=Starting a folder name with the token [USER_FOLDER] will allow matches of all user folders in the file system.
EditNonFullPathsRulePanel.modifiedWithinCheckbox.text=Modified within:
EditNonFullPathsRulePanel.folderNamesCheckbox.text=Folder names:
EditNonFullPathsRulePanel.fileNamesCheckbox.text=File names:
EditNonFullPathsRulePanel.extensionsCheckbox.text=Extensions:
EditNonFullPathsRulePanel.filenamesScrollPane.toolTipText=
EditNonFullPathsRulePanel.maxSizeCheckbox.text=Maximum size:
EditNonFullPathsRulePanel.minSizeCheckbox.text=Minimum size:
NewRulePanel.chooseLabel.text=Choose the type of rule
ConfigVisualPanel1.configureDriveRadioButton.text_1=Configure selected external drive:
ConfigVisualPanel1.configureFolderRadioButton.text_1=Configure in a folder:
ConfigVisualPanel1.descriptionTextArea.text=Select a location for the Logical Imager. This location will contain the imaging program and a configuration file. If that location already contains a configuration file, it will be loaded to edit. Imaging results will be saved to this location, so ensure it has enough free space.
ConfigVisualPanel1.refreshButton.text=Refresh
ConfigVisualPanel3.saveButton.text=Save
ConfigVisualPanel3.configLabel.text=Logical Imager config file save status:
ConfigVisualPanel3.executableLabel.text=Logical Imager executable save status:
ConfigVisualPanel3.executableStatusLabel.text=
EditFullPathsRulePanel.jLabel1.text=Description (Optional):
EditNonFullPathsRulePanel.jLabel2.text=Folder name matches are case insensitive and occur anywhere in a path.
EditNonFullPathsRulePanel.descriptionLabel.text=Description (Optional):
EditNonFullPathsRulePanel.jLabel1.text=If file is found:
EditFullPathsRulePanel.jLabel2.text=If file is found:
ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text=Alert if encryption programs are found
ConfigVisualPanel2.finalizeImageWriter.text=Continue imaging after searches are performed
EditNonFullPathsRulePanel.fileNamesInfoLabel.text=File names are case insensitive.
EditNonFullPathsRulePanel.extensionsInfoLabel.text=Extensions are case insensitive.

View File

@ -1,4 +1,3 @@
ConfigureLogicalImager.title=Configure Logical Imager
ConfigureLogicalImagerDialog.loadButton.text=Load
ConfigureLogicalImagerDialog.newButton.text=New
ConfigureLogicalImagerDialog.title=Configure Logical Imager
@ -29,22 +28,32 @@ ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty
ConfigVisualPanel1.configurationError=Configuration error
ConfigVisualPanel1.fileNameExtensionFilter=Configuration JSON File
ConfigVisualPanel1.invalidConfigJson=Invalid config JSON:
ConfigVisualPanel1.selectConfigurationFile=Select configuration file
ConfigVisualPanel1.messageLabel.noExternalDriveFound=No drive found
ConfigVisualPanel1.selectConfigurationFile=Select location
ConfigVisualPanel2.cancel=Cancel
ConfigVisualPanel2.deleteRuleSet=Delete rule
ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule confirmation
ConfigVisualPanel2.editConfiguration=Edit configuration
ConfigVisualPanel2.editConfiguration=Configure imager
ConfigVisualPanel2.editRuleError=Edit rule error
ConfigVisualPanel2.editRuleSet=Edit rule
ConfigVisualPanel2.editRuleSet=Edit Rule
ConfigVisualPanel2.newRule.name=New Rule
ConfigVisualPanel2.ok=OK
ConfigVisualPanel2.rulesTable.columnModel.title0=Rule Name
ConfigVisualPanel2.rulesTable.columnModel.title1=Description
ConfigVisualPanel3.copyStatus.error=Unable to save file
ConfigVisualPanel3.copyStatus.notSaved=File has not been saved
ConfigVisualPanel3.copyStatus.saved=Saved
ConfigVisualPanel3.copyStatus.savingInProgress=Saving file, please wait
# {0} - configurationLocation
ConfigVisualPanel3.description.text=Press Save to write the imaging tool and configuration file to the destination.\nDestination: {0}
# {0} - configFilename
ConfigWizardPanel2.failedToSaveConfigMsg=Failed to save configuration file: {0}
ConfigWizardPanel2.failedToSaveExeMsg=Failed to save tsk_logical_imager.exe file
ConfigVisualPanel3.failedToSaveConfigMsg=Failed to save configuration file: {0}
ConfigVisualPanel3.failedToSaveExeMsg=Failed to save tsk_logical_imager.exe file
# {0} - reason
ConfigWizardPanel2.reason=\nReason:
CTL_ConfigureLogicalImager=Create Logical Imager
ConfigVisualPanel3.reason=\nReason:
ConfigVisualPanel3.saveConfigurationFile=Save imager
CreateLogicalImagerAction.title=Create Logical Imager
CTL_CreateLogicalImagerAction=Create Logical Imager
EditFullPathsRulePanel.example=Example:
EditFullPathsRulePanel.fullPaths=Full paths
EditNonFullPathsRulePanel.emptyExtensionException=Extensions cannot have an empty entry
@ -56,16 +65,22 @@ EditNonFullPathsRulePanel.maxFileSizeMustBeNumberException=Maximum file size mus
EditNonFullPathsRulePanel.maxFileSizeNotPositiveException=Maximum file size must be a positive
# {0} - maxFileSize
# {1} - minFileSize
EditNonFullPathsRulePanel.maxFileSizeSmallerThanMinException=Maximum file size: {0} must be bigger than minimum file size: {1}
EditNonFullPathsRulePanel.maxFileSizeSmallerThanMinException=Maximum file size: {0} bytes must be bigger than minimum file size: {1} bytes
# {0} - message
EditNonFullPathsRulePanel.minFileSizeMustBeNumberException=Minimum file size must be a number: {0}
EditNonFullPathsRulePanel.minFileSizeNotPositiveException=Minimum file size must be a positive
# {0} - message
EditNonFullPathsRulePanel.modifiedDaysMustBeNumberException=Modified days must be a number: {0}
EditNonFullPathsRulePanel.modifiedDaysNotPositiveException=Modified days must be a positive
EditNonFullPathsRulePanel.note=NOTE: A special [USER_FOLDER] token at the the start of a folder name to allow matches of all user folders in the file system.
EditNonFullPathsRulePanel.units.bytes=Bytes
EditNonFullPathsRulePanel.units.gigabytes=Gigabytes
EditNonFullPathsRulePanel.units.kilobytes=Kilobytes
EditNonFullPathsRulePanel.units.megabytes=MegaBytes
# {0} - fieldName
EditRulePanel.blankLineException={0} cannot have a blank line
EditRulePanel.emptyRuleName.message=Rule name cannot be empty
# {0} - ruleName
EditRulePanel.reservedRuleName.message=Rule name "{0}" is reserved for use with a predefined rule
EditRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
EditRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
EditRulePanel.fullPathsLabel.text=Full paths:
@ -87,31 +102,21 @@ ConfigVisualPanel2.jCheckBox2.text=jCheckBox2
ConfigVisualPanel2.jTextField1.text=jTextField1
ConfigVisualPanel1.jRadioButton1.text=Create new configuration
ConfigVisualPanel1.jRadioButton2.text=Open existing configuration
ConfigVisualPanel1.jLabel1.text_1=Configuration file:
ConfigVisualPanel1.configFileTextField.text_1=
ConfigVisualPanel2.modifiedDateLabel.text=Modified Within:
ConfigVisualPanel2.folderNamesLabel.text=Folder names:
ConfigVisualPanel2.finalizeImageWriter.text=Continue imaging after searches are performed
ConfigVisualPanel2.filenamesLabel.text=File names:
ConfigVisualPanel2.extensionsTextField.text=
ConfigVisualPanel2.shouldAlertCheckBox.text=Alert in imager console if rule matches
ConfigVisualPanel2.shouldSaveCheckBox.text=Extract file if it matches a rule
ConfigVisualPanel2.deleteRuleButton.text=Delete Rule
ConfigVisualPanel2.descriptionEditTextField.text=
ConfigVisualPanel2.editRuleButton.text=Edit Rule
ConfigVisualPanel2.newRuleButton.text=New Rule
ConfigVisualPanel2.ruleNameEditTextField.text=
ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text=Alert if encryption programs are found
ConfigVisualPanel2.fullPathsLabel.text=Full paths:
ConfigVisualPanel2.daysIncludedLabel.text=day(s)
ConfigVisualPanel2.daysIncludedTextField.text=
ConfigVisualPanel2.configFileTextField.toolTipText=
ConfigVisualPanel2.configFileTextField.text=
ConfigVisualPanel2.filenamesTable.columnModel.title0=
ConfigVisualPanel2.fileSizeLabel.text=File size in bytes:
ConfigVisualPanel2.extensionsLabel.text=Extensions:
ConfigVisualPanel2.descriptionLabel.text=Description:
ConfigVisualPanel2.ruleNameLabel.text=Rule Name:
ConfigVisualPanel2.ruleNameLabel.text=Rule name:
ConfigVisualPanel2.ruleSetFileLabel.text=Configuration rule file:
EditRulePanel.ruleNameLabel.text=Rule Set:
EditRulePanel.descriptionTextField.text=
@ -129,52 +134,58 @@ EditRulePanel.jTable1.columnModel.title3=Title 4
EditRulePanel.jTable1.columnModel.title2=Title 3
EditRulePanel.jTable1.columnModel.title1=Title 2
EditRulePanel.shouldAlertCheckBox.actionCommand=
EditFullPathsRulePanel.ruleNameLabel.text=Rule Name:
EditFullPathsRulePanel.descriptionLabel.text=Description:
EditFullPathsRulePanel.descriptionTextField.text=
EditFullPathsRulePanel.ruleNameLabel.text=Rule name:
EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
EditFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
EditFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
EditFullPathsRulePanel.ruleNameTextField.text=
EditFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if a path matches
EditFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a path
EditFullPathsRulePanel.fullPathsLabel.text=Full paths:
EditFullPathsRulePanel.fullPathsLabel.toolTipText=
EditNonFullPathsRulePanel.ruleNameTextField.text=
EditNonFullPathsRulePanel.ruleNameLabel.text=Rule Name:
EditNonFullPathsRulePanel.descriptionLabel.text=Description:
EditNonFullPathsRulePanel.descriptionTextField.text=
EditNonFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a rule
EditNonFullPathsRulePanel.ruleNameLabel.text=Rule name:
EditNonFullPathsRulePanel.shouldSaveCheckBox.text=Extract file if it matches a condition
EditNonFullPathsRulePanel.daysIncludedLabel.text=day(s)
EditNonFullPathsRulePanel.modifiedDateLabel.text=Modified Within:
EditNonFullPathsRulePanel.fileSizeLabel.text=File size (bytes):
EditNonFullPathsRulePanel.folderNamesLabel.text=Folder names:
EditNonFullPathsRulePanel.filenamesLabel.text=File names:
EditNonFullPathsRulePanel.extensionsTextField.text=
EditNonFullPathsRulePanel.extensionsLabel.text=Extensions:
EditNonFullPathsRulePanel.shouldAlertCheckBox.actionCommand=
EditNonFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if rule matches
EditNonFullPathsRulePanel.shouldAlertCheckBox.text=Alert in imager console if a condition matches
ConfigVisualPanel1.browseButton.text=Browse
ConfigVisualPanel2.fullPathsTable.columnModel.title0=
ConfigVisualPanel2.folderNamesTable.columnModel.title0=
ConfigVisualPanel2.shouldSaveCheckBox.toolTipText=
EditRulePanel.validateRuleNameExceptionMsg=Rule name cannot be empty
ConfigVisualPanel2.maxSizeLabel.text=Maximum:
ConfigVisualPanel2.minSizeLabel.text=Minimum:
EditNonFullPathsRulePanel.minDaysTextField.text=jFormattedTextField1
ConfigVisualPanel1.browseButton.toolTipText=
EditNonFullPathsRulePanel.userFolderNote.text=Starting a folder name with the token [USER_FOLDER] will allow matches of all user folders in the file system.
EditNonFullPathsRulePanel.modifiedWithinCheckbox.text=Modified within:
EditNonFullPathsRulePanel.folderNamesCheckbox.text=Folder names:
EditNonFullPathsRulePanel.fileNamesCheckbox.text=File names:
EditNonFullPathsRulePanel.extensionsCheckbox.text=Extensions:
EditNonFullPathsRulePanel.filenamesScrollPane.toolTipText=
EditNonFullPathsRulePanel.maxSizeCheckbox.text=Maximum size:
EditNonFullPathsRulePanel.minSizeCheckbox.text=Minimum size:
EncryptionProgramsRule.encryptionProgramsRuleDescription=Find encryption programs
EncryptionProgramsRule.encryptionProgramsRuleName=Encryption Programs
LogicalImagerConfigDeserializer.fullPathsException=A rule with full-paths cannot have other rule definitions
LogicalImagerConfigDeserializer.missingRuleSetException=Missing rule-set
# {0} - key
LogicalImagerConfigDeserializer.unsupportedKeyException=Unsupported key: {0}
NewRuleSetPanel.chooseLabel.text=Choose the type of rule
EditNonFullPathsRulePanel.minSizeLabel.text=Minimum:
EditNonFullPathsRulePanel.maxSizeLabel.text=Maximum:
EditNonFullPathsRulePanel.minSizeTextField.text=
EditNonFullPathsRulePanel.maxSizeTextField.text=
ConfigVisualPanel2.maxSizeTextField.text=
ConfigVisualPanel2.maxSizeLabel.text=Maximum:
ConfigVisualPanel2.minSizeTextField.text=
ConfigVisualPanel2.minSizeLabel.text=Minimum:
EditNonFullPathsRulePanel.minDaysTextField.text=jFormattedTextField1
ConfigVisualPanel1.browseButton.toolTipText=
EditNonFullPathsRulePanel.extensionsRadioButton.text=
EditNonFullPathsRulePanel.filenamesRadioButton.text=
EditNonFullPathsRulePanel.extensionsRadioButton.toolTipText=Extensions and File names are mutually exclusive
EditNonFullPathsRulePanel.filenamesRadioButton.toolTipText=Extensions and File names are mutually exclusive
NewRulePanel.chooseLabel.text=Choose the type of rule
ConfigVisualPanel1.configureDriveRadioButton.text_1=Configure selected external drive:
ConfigVisualPanel1.configureFolderRadioButton.text_1=Configure in a folder:
ConfigVisualPanel1.descriptionTextArea.text=Select a location for the Logical Imager. This location will contain the imaging program and a configuration file. If that location already contains a configuration file, it will be loaded to edit. Imaging results will be saved to this location, so ensure it has enough free space.
ConfigVisualPanel1.refreshButton.text=Refresh
ConfigVisualPanel3.saveButton.text=Save
ConfigVisualPanel3.configLabel.text=Logical Imager config file save status:
ConfigVisualPanel3.executableLabel.text=Logical Imager executable save status:
ConfigVisualPanel3.executableStatusLabel.text=
EditFullPathsRulePanel.jLabel1.text=Description (Optional):
EditNonFullPathsRulePanel.jLabel2.text=Folder name matches are case insensitive and occur anywhere in a path.
EditNonFullPathsRulePanel.descriptionLabel.text=Description (Optional):
EditNonFullPathsRulePanel.jLabel1.text=If file is found:
EditFullPathsRulePanel.jLabel2.text=If file is found:
ConfigVisualPanel2.flagEncryptionProgramsCheckBox.text=Alert if encryption programs are found
ConfigVisualPanel2.finalizeImageWriter.text=Continue imaging after searches are performed
EditNonFullPathsRulePanel.fileNamesInfoLabel.text=File names are case insensitive.
EditNonFullPathsRulePanel.extensionsInfoLabel.text=Extensions are case insensitive.
NewRuleSetPanel.attributeRule.description=Search for files based on one or more attributes or metadata fields.
NewRuleSetPanel.attributeRule.name=Attribute
NewRuleSetPanel.fullPathRule.description=Search for files based on full exact match path.
NewRuleSetPanel.fullPathRule.name=Full Path

View File

@ -2,7 +2,7 @@
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Component class="javax.swing.ButtonGroup" name="buttonGroup1">
<Component class="javax.swing.ButtonGroup" name="configurationLocationButtonGroup">
</Component>
</NonVisualComponents>
<AuxValues>
@ -20,14 +20,31 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="38" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<Component id="configFileTextField" pref="279" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="warningLabel" max="32767" attributes="0"/>
<Component id="descriptionScrollPane" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="21" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="driveListScrollPane" alignment="1" min="-2" pref="437" max="-2" attributes="0"/>
<Component id="configFileTextField" alignment="0" min="-2" pref="437" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="refreshButton" min="-2" pref="87" max="-2" attributes="0"/>
<Component id="browseButton" min="-2" pref="87" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="configureDriveRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="configureFolderRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@ -35,32 +52,37 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="116" max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="configFileTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="descriptionScrollPane" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="13" max="-2" attributes="0"/>
<Component id="configureDriveRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="driveListScrollPane" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="95" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="141" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="configureFolderRadioButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="configFileTextField" min="-2" max="-2" attributes="0"/>
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="warningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="60" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.jLabel1.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="configFileTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.configFileTextField.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="browseButton">
@ -71,10 +93,109 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.browseButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="descriptionScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="descriptionTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" red="f0" type="rgb"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="11" style="0"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="4"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.descriptionTextArea.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JRadioButton" name="configureDriveRadioButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="configurationLocationButtonGroup"/>
</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/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.configureDriveRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="configureDriveRadioButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="configureFolderRadioButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="configurationLocationButtonGroup"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.configureFolderRadioButton.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="configureFolderRadioButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="driveListScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JList" name="driveList">
<Properties>
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.editors2.ListModelEditor">
<StringArray count="0"/>
</Property>
<Property name="selectionMode" type="int" value="0"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="mouseReleased" listener="java.awt.event.MouseListener" parameters="java.awt.event.MouseEvent" handler="driveListMouseReleasedSelection"/>
<EventHandler event="keyReleased" listener="java.awt.event.KeyListener" parameters="java.awt.event.KeyEvent" handler="driveListKeyReleasedSelection"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JButton" name="refreshButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel1.refreshButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="refreshButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="warningLabel">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,14 +28,25 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileStore;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.SwingUtilities;
import javax.swing.filechooser.FileFilter;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.filechooser.FileSystemView;
import org.apache.commons.lang.StringUtils;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.logicalimager.dsp.DriveListUtils;
/**
* Configuration Visual Panel 1
@ -43,9 +54,11 @@ import org.openide.util.NbBundle;
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class ConfigVisualPanel1 extends JPanel {
private LogicalImagerConfig config;
private static final Logger logger = Logger.getLogger(ConfigVisualPanel1.class.getName());
private static final long serialVersionUID = 1L;
private static final String DEFAULT_CONFIG_FILE_NAME = "logical-imager-config.json";
private static final String UPDATE_UI_EVENT_NAME = "UPDATE_UI";
private String configFilename;
private boolean newFile = true;
/**
* Creates new form ConfigVisualPanel1
@ -53,10 +66,14 @@ final class ConfigVisualPanel1 extends JPanel {
ConfigVisualPanel1() {
initComponents();
configFileTextField.getDocument().addDocumentListener(new MyDocumentListener(this));
refreshDriveList();
SwingUtilities.invokeLater(() -> {
updateControls();
});
}
@NbBundle.Messages({
"ConfigVisualPanel1.selectConfigurationFile=Select configuration file"
"ConfigVisualPanel1.selectConfigurationFile=Select location"
})
@Override
public String getName() {
@ -71,47 +88,129 @@ final class ConfigVisualPanel1 extends JPanel {
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
jLabel1 = new javax.swing.JLabel();
configurationLocationButtonGroup = new javax.swing.ButtonGroup();
configFileTextField = new javax.swing.JTextField();
browseButton = new javax.swing.JButton();
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.jLabel1.text_1")); // NOI18N
descriptionScrollPane = new javax.swing.JScrollPane();
descriptionTextArea = new javax.swing.JTextArea();
configureDriveRadioButton = new javax.swing.JRadioButton();
configureFolderRadioButton = new javax.swing.JRadioButton();
driveListScrollPane = new javax.swing.JScrollPane();
driveList = new javax.swing.JList<>();
refreshButton = new javax.swing.JButton();
warningLabel = new javax.swing.JLabel();
configFileTextField.setEditable(false);
configFileTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configFileTextField.text_1")); // NOI18N
configFileTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(browseButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.browseButton.text")); // NOI18N
browseButton.setToolTipText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.browseButton.toolTipText")); // NOI18N
browseButton.setEnabled(false);
browseButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
}
});
descriptionTextArea.setEditable(false);
descriptionTextArea.setBackground(new java.awt.Color(240, 240, 240));
descriptionTextArea.setColumns(20);
descriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
descriptionTextArea.setLineWrap(true);
descriptionTextArea.setRows(4);
descriptionTextArea.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.descriptionTextArea.text")); // NOI18N
descriptionTextArea.setWrapStyleWord(true);
descriptionTextArea.setEnabled(false);
descriptionScrollPane.setViewportView(descriptionTextArea);
configurationLocationButtonGroup.add(configureDriveRadioButton);
configureDriveRadioButton.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(configureDriveRadioButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configureDriveRadioButton.text_1")); // NOI18N
configureDriveRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
configureDriveRadioButtonActionPerformed(evt);
}
});
configurationLocationButtonGroup.add(configureFolderRadioButton);
org.openide.awt.Mnemonics.setLocalizedText(configureFolderRadioButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.configureFolderRadioButton.text_1")); // NOI18N
configureFolderRadioButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
configureFolderRadioButtonActionPerformed(evt);
}
});
driveList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
driveList.setEnabled(false);
driveList.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseReleased(java.awt.event.MouseEvent evt) {
driveListMouseReleasedSelection(evt);
}
});
driveList.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
driveListKeyReleasedSelection(evt);
}
});
driveListScrollPane.setViewportView(driveList);
org.openide.awt.Mnemonics.setLocalizedText(refreshButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel1.class, "ConfigVisualPanel1.refreshButton.text")); // NOI18N
refreshButton.setEnabled(false);
refreshButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
refreshButtonActionPerformed(evt);
}
});
warningLabel.setForeground(new java.awt.Color(255, 0, 0));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(38, 38, 38)
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1)
.addComponent(configFileTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 279, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(browseButton)
.addComponent(warningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(descriptionScrollPane)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(driveListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 437, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(configFileTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 437, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(refreshButton, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(configureDriveRadioButton)
.addComponent(configureFolderRadioButton))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(116, 116, 116)
.addComponent(jLabel1)
.addContainerGap()
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(13, 13, 13)
.addComponent(configureDriveRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(driveListScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(refreshButton)
.addGap(0, 95, Short.MAX_VALUE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(configureFolderRadioButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(configFileTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(browseButton))
.addContainerGap(141, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(warningLabel)
.addContainerGap(60, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
@ -119,23 +218,99 @@ final class ConfigVisualPanel1 extends JPanel {
"ConfigVisualPanel1.chooseFileTitle=Select a Logical Imager configuration"
})
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
chooseFile(Bundle.ConfigVisualPanel1_chooseFileTitle());
chooseFile(Bundle.ConfigVisualPanel1_chooseFileTitle());
}//GEN-LAST:event_browseButtonActionPerformed
private void configureFolderRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configureFolderRadioButtonActionPerformed
updateControls();
}//GEN-LAST:event_configureFolderRadioButtonActionPerformed
private void configureDriveRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_configureDriveRadioButtonActionPerformed
updateControls();
}//GEN-LAST:event_configureDriveRadioButtonActionPerformed
private void refreshButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_refreshButtonActionPerformed
refreshDriveList();
}//GEN-LAST:event_refreshButtonActionPerformed
private void driveListKeyReleasedSelection(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_driveListKeyReleasedSelection
firePropertyChange(UPDATE_UI_EVENT_NAME, false, true); // NON-NLS
}//GEN-LAST:event_driveListKeyReleasedSelection
private void driveListMouseReleasedSelection(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_driveListMouseReleasedSelection
firePropertyChange(UPDATE_UI_EVENT_NAME, false, true); // NON-NLS
}//GEN-LAST:event_driveListMouseReleasedSelection
/**
* Refresh the list of local drives on the current machine
*/
@Messages({"ConfigVisualPanel1.messageLabel.noExternalDriveFound=No drive found"})
private void refreshDriveList() {
List<String> listData = new ArrayList<>();
File[] roots = File.listRoots();
int firstRemovableDrive = -1;
int i = 0;
for (File root : roots) {
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
long spaceInBytes = root.getTotalSpace();
String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, false);
listData.add(root + " (" + description + ") (" + sizeWithUnit + ")");
if (firstRemovableDrive == -1) {
try {
FileStore fileStore = Files.getFileStore(root.toPath());
if ((boolean) fileStore.getAttribute("volume:isRemovable")) { //NON-NLS
firstRemovableDrive = i;
}
} catch (IOException ignored) {
//unable to get this removable drive for default selection will try and select next removable drive by default
logger.log(Level.INFO, "Unable to select first removable drive found", ignored);
}
}
i++;
}
driveList.setListData(listData.toArray(new String[listData.size()]));
if (!listData.isEmpty()) {
// auto-select the first external drive, if any
driveList.setSelectedIndex(firstRemovableDrive == -1 ? 0 : firstRemovableDrive);
firePropertyChange(UPDATE_UI_EVENT_NAME, false, true); // NON-NLS
driveList.requestFocusInWindow();
warningLabel.setText("");
} else {
warningLabel.setText(Bundle.ConfigVisualPanel1_messageLabel_noExternalDriveFound());
}
}
/**
* Update which controls are enabled to reflect the current radio button
* selection.
*/
private void updateControls() {
browseButton.setEnabled(configureFolderRadioButton.isSelected());
refreshButton.setEnabled(configureDriveRadioButton.isSelected());
driveList.setEnabled(configureDriveRadioButton.isSelected());
driveListScrollPane.setEnabled(configureDriveRadioButton.isSelected());
firePropertyChange(UPDATE_UI_EVENT_NAME, false, true); // NON-NLS
}
/**
* Open a file chooser to allow users to choose a json configuration file in
* a folder.
*
* @param title the dialog title
*/
@NbBundle.Messages({
"ConfigVisualPanel1.fileNameExtensionFilter=Configuration JSON File",
"ConfigVisualPanel1.invalidConfigJson=Invalid config JSON: ",
"ConfigVisualPanel1.configurationError=Configuration error",
})
"ConfigVisualPanel1.configurationError=Configuration error",})
private void chooseFile(String title) {
final String jsonExt = ".json"; // NON-NLS
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle(title);
fileChooser.setDragEnabled(false);
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
FileFilter filter = new FileNameExtensionFilter(Bundle.ConfigVisualPanel1_fileNameExtensionFilter(), new String[] {"json"}); // NON-NLS
FileFilter filter = new FileNameExtensionFilter(Bundle.ConfigVisualPanel1_fileNameExtensionFilter(), new String[]{"json"}); // NON-NLS
fileChooser.setFileFilter(filter);
fileChooser.setSelectedFile(new File("logical-imager-config.json")); // default
fileChooser.setSelectedFile(new File(DEFAULT_CONFIG_FILE_NAME)); // default
fileChooser.setMultiSelectionEnabled(false);
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
String path = fileChooser.getSelectedFile().getPath();
@ -144,12 +319,11 @@ final class ConfigVisualPanel1 extends JPanel {
loadConfigFile(path);
configFilename = path;
configFileTextField.setText(path);
newFile = false;
} catch (JsonIOException | JsonSyntaxException | IOException ex) {
JOptionPane.showMessageDialog(this,
Bundle.ConfigVisualPanel1_invalidConfigJson() + ex.getMessage() ,
Bundle.ConfigVisualPanel1_configurationError(),
JOptionPane.ERROR_MESSAGE);
JOptionPane.showMessageDialog(this,
Bundle.ConfigVisualPanel1_invalidConfigJson() + ex.getMessage(),
Bundle.ConfigVisualPanel1_configurationError(),
JOptionPane.ERROR_MESSAGE);
}
} else {
if (!path.endsWith(jsonExt)) {
@ -157,55 +331,117 @@ final class ConfigVisualPanel1 extends JPanel {
}
configFilename = path;
configFileTextField.setText(path);
config = new LogicalImagerConfig();
newFile = true;
}
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton browseButton;
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.JTextField configFileTextField;
private javax.swing.JLabel jLabel1;
private javax.swing.ButtonGroup configurationLocationButtonGroup;
private javax.swing.JRadioButton configureDriveRadioButton;
private javax.swing.JRadioButton configureFolderRadioButton;
private javax.swing.JScrollPane descriptionScrollPane;
private javax.swing.JTextArea descriptionTextArea;
private javax.swing.JList<String> driveList;
private javax.swing.JScrollPane driveListScrollPane;
private javax.swing.JButton refreshButton;
private javax.swing.JLabel warningLabel;
// End of variables declaration//GEN-END:variables
/**
* Load a json config file specified by the path argument.
*
*
* @param path the path of the json config to load
*
* @return the LogicalImagerConfig which contains the rules from the loaded
* config.
*
* @throws FileNotFoundException
* @throws JsonIOException
* @throws JsonSyntaxException
* @throws IOException
*/
@NbBundle.Messages({
"# {0} - filename",
"ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty",
})
private void loadConfigFile(String path) throws FileNotFoundException, JsonIOException, JsonSyntaxException, IOException {
"ConfigVisualPanel1.configFileIsEmpty=Configuration file {0} is empty",})
private LogicalImagerConfig loadConfigFile(String path) throws FileNotFoundException, JsonIOException, JsonSyntaxException, IOException {
try (FileInputStream is = new FileInputStream(path)) {
InputStreamReader reader = new InputStreamReader(is, StandardCharsets.UTF_8);
GsonBuilder gsonBuilder = new GsonBuilder().setPrettyPrinting();
gsonBuilder.registerTypeAdapter(LogicalImagerConfig.class, new LogicalImagerConfigDeserializer());
Gson gson = gsonBuilder.create();
config = gson.fromJson(reader, LogicalImagerConfig.class);
if (config == null) {
LogicalImagerConfig loadedConfig = gson.fromJson(reader, LogicalImagerConfig.class);
if (loadedConfig == null) {
// This happens if the file is empty. Gson doesn't call the deserializer and doesn't throw any exception.
throw new IOException(Bundle.ConfigVisualPanel1_configFileIsEmpty(path));
}
return loadedConfig;
}
}
/**
* Get the LogicalImagerConfig for the currently selected config file.
*
* @return the LogicalImagerConfig which contains the rules from the loaded
* config.
*/
LogicalImagerConfig getConfig() {
return config;
String configFileName = getConfigPath();
if (configFileName != null && new File(configFileName).exists()) {
try {
return loadConfigFile(configFileName);
} catch (JsonIOException | JsonSyntaxException | IOException ex) {
return new LogicalImagerConfig();
}
} else {
return new LogicalImagerConfig();
}
}
String getConfigFilename() {
return configFilename;
/**
* Get the path of the currently selected json config file.
*
* @return the path of the currently selected config file or null if invalid
* settings are selected
*/
String getConfigPath() {
if (configureFolderRadioButton.isSelected()) {
return configFilename;
} else {
String selectedStr = driveList.getSelectedValue();
if (selectedStr == null) {
return null;
}
return selectedStr.substring(0, 3) + DEFAULT_CONFIG_FILE_NAME;
}
}
boolean isNewFile() {
return newFile;
/**
* The name of the event which signifies an update to the settings reflected
* by ConfigVisualPanel1
*
* @return UPDATE_UI_EVENT_NAME
*/
static String getUpdateEventName() {
return UPDATE_UI_EVENT_NAME;
}
void setConfigFilename(String filename) {
void setConfigFilename(String filename
) {
configFileTextField.setText(filename);
}
/**
* Checks if the current panel has valid settings selected.
*
* @return true if panel has valid settings selected, false otherwise
*/
boolean isPanelValid() {
return (newFile || !configFileTextField.getText().isEmpty());
return !StringUtils.isBlank(getConfigPath()) && ((configureDriveRadioButton.isSelected() && !StringUtils.isBlank(driveList.getSelectedValue()))
|| (configureFolderRadioButton.isSelected() && (!configFileTextField.getText().isEmpty())));
}
/**
@ -214,7 +450,7 @@ final class ConfigVisualPanel1 extends JPanel {
private static class MyDocumentListener implements DocumentListener {
private final ConfigVisualPanel1 panel;
MyDocumentListener(ConfigVisualPanel1 aThis) {
this.panel = aThis;
}
@ -235,7 +471,7 @@ final class ConfigVisualPanel1 extends JPanel {
}
private void fireChange() {
panel.firePropertyChange("UPDATE_UI", false, true); // NON-NLS
panel.firePropertyChange(UPDATE_UI_EVENT_NAME, false, true); // NON-NLS
}
}

View File

@ -16,98 +16,86 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="480" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="daysIncludedTextField" min="-2" pref="54" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="daysIncludedLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="ruleNameEditTextField" alignment="0" max="32767" attributes="0"/>
<Component id="descriptionEditTextField" alignment="0" max="32767" attributes="0"/>
<Component id="extensionsTextField" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane5" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane6" alignment="0" max="32767" attributes="0"/>
<Component id="jScrollPane7" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="jScrollPane1" min="-2" pref="377" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="newRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<Component id="editRuleButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="37" max="-2" attributes="0"/>
<Component id="deleteRuleButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="flagEncryptionProgramsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="finalizeImageWriter" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="393" pref="393" max="-2" attributes="0"/>
<Component id="shouldSaveCheckBox" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="397" pref="397" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="extensionsLabel" min="-2" max="-2" attributes="0"/>
<Component id="filenamesLabel" min="-2" max="-2" attributes="0"/>
<Component id="descriptionLabel" min="-2" max="-2" attributes="0"/>
<Component id="ruleNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="397" pref="397" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="modifiedDateLabel" alignment="0" min="-2" pref="79" max="-2" attributes="0"/>
<Component id="fileSizeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fullPathsLabel" min="-2" max="-2" attributes="0"/>
<Component id="folderNamesLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Component id="minSizeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="minSizeTextField" min="-2" pref="63" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="maxSizeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="maxSizeTextField" min="-2" pref="63" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="393" pref="393" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
<Component id="ruleSetFileLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="configFileTextField" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="17" max="-2" attributes="0"/>
<Component id="ruleSetFileLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="configFileTextField" max="32767" attributes="0"/>
<Component id="newRuleButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="editRuleButton" linkSize="3" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="deleteRuleButton" linkSize="3" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="rulesScrollPane" alignment="1" min="-2" pref="341" max="-2" attributes="0"/>
</Group>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="flagEncryptionProgramsCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="finalizeImageWriter" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="shouldSaveCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="extensionsLabel" min="-2" max="-2" attributes="0"/>
<Component id="filenamesLabel" min="-2" max="-2" attributes="0"/>
<Component id="descriptionLabel" min="-2" max="-2" attributes="0"/>
<Component id="ruleNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="modifiedDateLabel" alignment="0" min="-2" pref="79" max="-2" attributes="0"/>
<Component id="fileSizeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fullPathsLabel" min="-2" max="-2" attributes="0"/>
<Component id="folderNamesLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="4" max="-2" attributes="0"/>
<Component id="minSizeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="minSizeTextField" min="-2" pref="63" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="maxSizeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="maxSizeTextField" min="-2" pref="63" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace min="-2" pref="107" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="129" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="modifiedWithinTextField" min="-2" pref="54" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="daysIncludedLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="ruleNameEditTextField" alignment="0" max="32767" attributes="0"/>
<Component id="descriptionEditTextField" alignment="0" max="32767" attributes="0"/>
<Component id="extensionsTextField" alignment="0" max="32767" attributes="0"/>
<Component id="fullPathsScrollPane" alignment="0" pref="0" max="32767" attributes="0"/>
<Component id="filenamesScrollPane" alignment="0" pref="0" max="32767" attributes="0"/>
<Component id="folderNamesScrollPane" alignment="0" pref="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</Group>
<Group type="102" attributes="0">
<EmptySpace min="397" pref="397" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator1" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -122,7 +110,7 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jScrollPane1" pref="527" max="32767" attributes="0"/>
<Component id="rulesScrollPane" pref="479" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="newRuleButton" alignment="3" min="-2" max="-2" attributes="0"/>
@ -151,7 +139,7 @@
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane6" pref="0" max="32767" attributes="0"/>
<Component id="filenamesScrollPane" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="filenamesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
@ -159,7 +147,7 @@
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane7" pref="0" max="32767" attributes="0"/>
<Component id="folderNamesScrollPane" pref="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="folderNamesLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
@ -172,7 +160,7 @@
<EmptySpace max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="1" attributes="0">
<Component id="jScrollPane5" pref="0" max="32767" attributes="0"/>
<Component id="fullPathsScrollPane" pref="0" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
</Group>
</Group>
@ -186,14 +174,14 @@
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="modifiedDateLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="daysIncludedTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="modifiedWithinTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="daysIncludedLabel" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="shouldSaveCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" pref="2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="flagEncryptionProgramsCheckBox" min="-2" max="-2" attributes="0"/>
@ -214,13 +202,10 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="daysIncludedTextField">
<Component class="javax.swing.JTextField" name="modifiedWithinTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="horizontalAlignment" type="int" value="11"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.daysIncludedTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[60, 20]"/>
@ -264,9 +249,6 @@
</Component>
<Component class="javax.swing.JTextField" name="ruleNameEditTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.ruleNameEditTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
@ -305,9 +287,6 @@
</Component>
<Component class="javax.swing.JTextField" name="descriptionEditTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.descriptionEditTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
@ -324,7 +303,7 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="deleteRuleButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane5">
<Container class="javax.swing.JScrollPane" name="fullPathsScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
@ -358,7 +337,7 @@
</Component>
</SubComponents>
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane6">
<Container class="javax.swing.JScrollPane" name="filenamesScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
@ -396,7 +375,6 @@
</Container>
<Component class="javax.swing.JCheckBox" name="shouldSaveCheckBox">
<Properties>
<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/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.shouldSaveCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
@ -408,14 +386,13 @@
</Component>
<Component class="javax.swing.JCheckBox" name="shouldAlertCheckBox">
<Properties>
<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/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.shouldAlertCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane7">
<Container class="javax.swing.JScrollPane" name="folderNamesScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
@ -460,9 +437,6 @@
</Component>
<Component class="javax.swing.JTextField" name="extensionsTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.extensionsTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
@ -475,12 +449,7 @@
</Component>
<Component class="javax.swing.JTextField" name="configFileTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.configFileTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.configFileTextField.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" value=""/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
@ -501,7 +470,7 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="finalizeImageWriterActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JScrollPane" name="jScrollPane1">
<Container class="javax.swing.JScrollPane" name="rulesScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
@ -576,9 +545,6 @@
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
<Format format="#,###; " subtype="-1" type="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.minSizeTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
@ -594,9 +560,6 @@
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
<Format format="#,###; " subtype="-1" type="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel2.maxSizeTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,6 +30,7 @@ import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
/**
* Configuration Visual Panel 2
@ -41,13 +42,13 @@ import org.openide.util.NbBundle;
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class ConfigVisualPanel2 extends JPanel {
private static final List<String> EMPTY_LIST = new ArrayList<>();
private static final long serialVersionUID = 1L;
private String configFilename;
private LogicalImagerConfig config = null;
private final JButton okButton = new JButton(Bundle.ConfigVisualPanel2_ok());
private final JButton cancelButton = new JButton(Bundle.ConfigVisualPanel2_cancel());
private boolean flagEncryptionPrograms = false;
/**
* Creates new form ConfigVisualPanel2
*/
@ -59,7 +60,7 @@ final class ConfigVisualPanel2 extends JPanel {
}
@NbBundle.Messages({
"ConfigVisualPanel2.editConfiguration=Edit configuration"
"ConfigVisualPanel2.editConfiguration=Configure imager"
})
@Override
public String getName() {
@ -75,7 +76,7 @@ final class ConfigVisualPanel2 extends JPanel {
private void initComponents() {
modifiedDateLabel = new javax.swing.JLabel();
daysIncludedTextField = new javax.swing.JTextField();
modifiedWithinTextField = new javax.swing.JTextField();
daysIncludedLabel = new javax.swing.JLabel();
fullPathsLabel = new javax.swing.JLabel();
flagEncryptionProgramsCheckBox = new javax.swing.JCheckBox();
@ -86,13 +87,13 @@ final class ConfigVisualPanel2 extends JPanel {
editRuleButton = new javax.swing.JButton();
descriptionEditTextField = new javax.swing.JTextField();
deleteRuleButton = new javax.swing.JButton();
jScrollPane5 = new javax.swing.JScrollPane();
fullPathsScrollPane = new javax.swing.JScrollPane();
fullPathsTable = new javax.swing.JTable();
jScrollPane6 = new javax.swing.JScrollPane();
filenamesScrollPane = new javax.swing.JScrollPane();
filenamesTable = new javax.swing.JTable();
shouldSaveCheckBox = new javax.swing.JCheckBox();
shouldAlertCheckBox = new javax.swing.JCheckBox();
jScrollPane7 = new javax.swing.JScrollPane();
folderNamesScrollPane = new javax.swing.JScrollPane();
folderNamesTable = new javax.swing.JTable();
extensionsLabel = new javax.swing.JLabel();
extensionsTextField = new javax.swing.JTextField();
@ -100,7 +101,7 @@ final class ConfigVisualPanel2 extends JPanel {
configFileTextField = new javax.swing.JTextField();
ruleSetFileLabel = new javax.swing.JLabel();
finalizeImageWriter = new javax.swing.JCheckBox();
jScrollPane1 = new javax.swing.JScrollPane();
rulesScrollPane = new javax.swing.JScrollPane();
rulesTable = new javax.swing.JTable();
folderNamesLabel = new javax.swing.JLabel();
fileSizeLabel = new javax.swing.JLabel();
@ -112,12 +113,11 @@ final class ConfigVisualPanel2 extends JPanel {
org.openide.awt.Mnemonics.setLocalizedText(modifiedDateLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.modifiedDateLabel.text")); // NOI18N
daysIncludedTextField.setEditable(false);
daysIncludedTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
daysIncludedTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.daysIncludedTextField.text")); // NOI18N
daysIncludedTextField.setEnabled(false);
daysIncludedTextField.setMinimumSize(new java.awt.Dimension(60, 20));
daysIncludedTextField.setPreferredSize(new java.awt.Dimension(60, 20));
modifiedWithinTextField.setEditable(false);
modifiedWithinTextField.setHorizontalAlignment(javax.swing.JTextField.TRAILING);
modifiedWithinTextField.setEnabled(false);
modifiedWithinTextField.setMinimumSize(new java.awt.Dimension(60, 20));
modifiedWithinTextField.setPreferredSize(new java.awt.Dimension(60, 20));
org.openide.awt.Mnemonics.setLocalizedText(daysIncludedLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.daysIncludedLabel.text")); // NOI18N
daysIncludedLabel.setEnabled(false);
@ -133,7 +133,6 @@ final class ConfigVisualPanel2 extends JPanel {
org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.ruleNameLabel.text")); // NOI18N
ruleNameEditTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.ruleNameEditTextField.text")); // NOI18N
ruleNameEditTextField.setEnabled(false);
newRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/add16.png"))); // NOI18N
@ -154,7 +153,6 @@ final class ConfigVisualPanel2 extends JPanel {
}
});
descriptionEditTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.descriptionEditTextField.text")); // NOI18N
descriptionEditTextField.setEnabled(false);
deleteRuleButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/delete16.png"))); // NOI18N
@ -171,7 +169,7 @@ final class ConfigVisualPanel2 extends JPanel {
fullPathsTable.setShowHorizontalLines(false);
fullPathsTable.setShowVerticalLines(false);
fullPathsTable.getTableHeader().setReorderingAllowed(false);
jScrollPane5.setViewportView(fullPathsTable);
fullPathsScrollPane.setViewportView(fullPathsTable);
fullPathsTable.getColumnModel().getSelectionModel().setSelectionMode(javax.swing.ListSelectionModel.SINGLE_INTERVAL_SELECTION);
if (fullPathsTable.getColumnModel().getColumnCount() > 0) {
fullPathsTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.fullPathsTable.columnModel.title0")); // NOI18N
@ -182,17 +180,15 @@ final class ConfigVisualPanel2 extends JPanel {
filenamesTable.setShowHorizontalLines(false);
filenamesTable.setShowVerticalLines(false);
filenamesTable.getTableHeader().setReorderingAllowed(false);
jScrollPane6.setViewportView(filenamesTable);
filenamesScrollPane.setViewportView(filenamesTable);
if (filenamesTable.getColumnModel().getColumnCount() > 0) {
filenamesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.filenamesTable.columnModel.title0")); // NOI18N
}
shouldSaveCheckBox.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(shouldSaveCheckBox, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.shouldSaveCheckBox.text")); // NOI18N
shouldSaveCheckBox.setToolTipText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.shouldSaveCheckBox.toolTipText")); // NOI18N
shouldSaveCheckBox.setEnabled(false);
shouldAlertCheckBox.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(shouldAlertCheckBox, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.shouldAlertCheckBox.text")); // NOI18N
shouldAlertCheckBox.setEnabled(false);
@ -201,20 +197,18 @@ final class ConfigVisualPanel2 extends JPanel {
folderNamesTable.setShowHorizontalLines(false);
folderNamesTable.setShowVerticalLines(false);
folderNamesTable.getTableHeader().setReorderingAllowed(false);
jScrollPane7.setViewportView(folderNamesTable);
folderNamesScrollPane.setViewportView(folderNamesTable);
if (folderNamesTable.getColumnModel().getColumnCount() > 0) {
folderNamesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.folderNamesTable.columnModel.title0")); // NOI18N
}
org.openide.awt.Mnemonics.setLocalizedText(extensionsLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.extensionsLabel.text")); // NOI18N
extensionsTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.extensionsTextField.text")); // NOI18N
extensionsTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(filenamesLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.filenamesLabel.text")); // NOI18N
configFileTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.configFileTextField.text")); // NOI18N
configFileTextField.setToolTipText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.configFileTextField.toolTipText")); // NOI18N
configFileTextField.setToolTipText("");
configFileTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(ruleSetFileLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.ruleSetFileLabel.text")); // NOI18N
@ -241,7 +235,7 @@ final class ConfigVisualPanel2 extends JPanel {
rulesTableKeyReleased(evt);
}
});
jScrollPane1.setViewportView(rulesTable);
rulesScrollPane.setViewportView(rulesTable);
if (rulesTable.getColumnModel().getColumnCount() > 0) {
rulesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.rulesTable.columnModel.title0")); // NOI18N
rulesTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.rulesTable.columnModel.title1")); // NOI18N
@ -254,13 +248,11 @@ final class ConfigVisualPanel2 extends JPanel {
org.openide.awt.Mnemonics.setLocalizedText(minSizeLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.minSizeLabel.text")); // NOI18N
minSizeTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,###; "))));
minSizeTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.minSizeTextField.text")); // NOI18N
minSizeTextField.setEnabled(false);
org.openide.awt.Mnemonics.setLocalizedText(maxSizeLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.maxSizeLabel.text")); // NOI18N
maxSizeTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#,###; "))));
maxSizeTextField.setText(org.openide.util.NbBundle.getMessage(ConfigVisualPanel2.class, "ConfigVisualPanel2.maxSizeTextField.text")); // NOI18N
maxSizeTextField.setEnabled(false);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
@ -268,78 +260,73 @@ final class ConfigVisualPanel2 extends JPanel {
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(480, 480, 480)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(daysIncludedLabel))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(ruleNameEditTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionEditTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extensionsTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane5, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane6, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane7, javax.swing.GroupLayout.Alignment.LEADING))
.addContainerGap())))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 377, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addComponent(newRuleButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(editRuleButton)
.addGap(37, 37, 37)
.addComponent(deleteRuleButton)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(flagEncryptionProgramsCheckBox)
.addComponent(finalizeImageWriter)))
.addGroup(layout.createSequentialGroup()
.addGap(393, 393, 393)
.addComponent(shouldSaveCheckBox))
.addGroup(layout.createSequentialGroup()
.addGap(397, 397, 397)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extensionsLabel)
.addComponent(filenamesLabel)
.addComponent(descriptionLabel)
.addComponent(ruleNameLabel)))
.addGroup(layout.createSequentialGroup()
.addGap(397, 397, 397)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(modifiedDateLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeLabel)
.addComponent(fullPathsLabel)
.addComponent(folderNamesLabel))
.addGap(4, 4, 4)
.addComponent(minSizeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(minSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(maxSizeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(maxSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createSequentialGroup()
.addGap(393, 393, 393)
.addComponent(shouldAlertCheckBox)))
.addGap(17, 17, 17)
.addComponent(ruleSetFileLabel)
.addGap(18, 18, 18)
.addComponent(configFileTextField)
.addContainerGap())
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(17, 17, 17)
.addComponent(ruleSetFileLabel)
.addGap(18, 18, 18)
.addComponent(configFileTextField))
.addComponent(newRuleButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(editRuleButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(deleteRuleButton))
.addComponent(rulesScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 341, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(397, 397, 397)
.addComponent(jSeparator1)))
.addGap(10, 10, 10))
.addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(flagEncryptionProgramsCheckBox)
.addComponent(finalizeImageWriter)
.addComponent(shouldSaveCheckBox)
.addComponent(shouldAlertCheckBox)
.addComponent(extensionsLabel)
.addComponent(filenamesLabel)
.addComponent(descriptionLabel)
.addComponent(ruleNameLabel)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(modifiedDateLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 79, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fileSizeLabel)
.addComponent(fullPathsLabel)
.addComponent(folderNamesLabel))
.addGap(4, 4, 4)
.addComponent(minSizeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(minSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(maxSizeLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(maxSizeTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 63, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(107, 107, 107))
.addGroup(layout.createSequentialGroup()
.addGap(129, 129, 129)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(modifiedWithinTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 54, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(daysIncludedLabel))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(ruleNameEditTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionEditTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(extensionsTextField, javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(fullPathsScrollPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(filenamesScrollPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(folderNamesScrollPane, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
.addContainerGap())))))
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1))))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {deleteRuleButton, editRuleButton, newRuleButton});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
@ -350,7 +337,7 @@ final class ConfigVisualPanel2 extends JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 527, Short.MAX_VALUE)
.addComponent(rulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 479, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newRuleButton)
@ -372,13 +359,13 @@ final class ConfigVisualPanel2 extends JPanel {
.addComponent(ruleNameLabel)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane6, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(filenamesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(filenamesLabel)
.addGap(0, 0, Short.MAX_VALUE)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane7, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(folderNamesScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(folderNamesLabel)
.addGap(0, 0, Short.MAX_VALUE)))
@ -388,7 +375,7 @@ final class ConfigVisualPanel2 extends JPanel {
.addComponent(fullPathsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(fullPathsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addGap(11, 11, 11)))
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(minSizeLabel)
@ -399,13 +386,13 @@ final class ConfigVisualPanel2 extends JPanel {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
.addComponent(modifiedDateLabel)
.addComponent(daysIncludedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(modifiedWithinTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(daysIncludedLabel))
.addGap(3, 3, 3)
.addComponent(shouldAlertCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(shouldSaveCheckBox)
.addGap(18, 18, 18)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(shouldAlertCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 2, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(flagEncryptionProgramsCheckBox)
@ -415,31 +402,27 @@ final class ConfigVisualPanel2 extends JPanel {
);
}// </editor-fold>//GEN-END:initComponents
private void finalizeImageWriterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_finalizeImageWriterActionPerformed
config.setFinalizeImageWriter(finalizeImageWriter.isSelected());
}//GEN-LAST:event_finalizeImageWriterActionPerformed
private void rulesTableKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_rulesTableKeyReleased
rulesTableSelect();
updateForSelectedRule();
}//GEN-LAST:event_rulesTableKeyReleased
@NbBundle.Messages({
"ConfigVisualPanel2.editRuleSet=Edit rule",
"ConfigVisualPanel2.editRuleSet=Edit Rule",
"ConfigVisualPanel2.editRuleError=Edit rule error"
})
private void editRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_editRuleButtonActionPerformed
int row = rulesTable.getSelectedRow();
if (row != -1) {
String ruleName = (String) rulesTable.getModel().getValueAt(row, 0);
LogicalImagerRule rule = getFirstRuleSet().getRules().get(row);
LogicalImagerRule rule = getRuleSetFromCurrentConfig().getRules().get(row);
EditRulePanel editPanel = new EditRulePanel(okButton, cancelButton, ruleName, rule);
editPanel.setEnabled(true);
editPanel.setVisible(true);
while (true) {
int option = JOptionPane.showOptionDialog(this, editPanel.getPanel(), Bundle.ConfigVisualPanel2_editRuleSet(),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
int option = JOptionPane.showOptionDialog(this, editPanel.getPanel(), Bundle.ConfigVisualPanel2_editRuleSet(),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
if (option == JOptionPane.OK_OPTION) {
try {
ImmutablePair<String, LogicalImagerRule> ruleMap = editPanel.toRule();
@ -447,28 +430,29 @@ final class ConfigVisualPanel2 extends JPanel {
break;
} catch (IOException | NumberFormatException ex) {
JOptionPane.showMessageDialog(this,
ex.getMessage(),
Bundle.ConfigVisualPanel2_editRuleError(),
JOptionPane.ERROR_MESSAGE);
ex.getMessage(),
Bundle.ConfigVisualPanel2_editRuleError(),
JOptionPane.ERROR_MESSAGE);
// let user fix the error
}
} else {
break;
}
}
}
}
}//GEN-LAST:event_editRuleButtonActionPerformed
@Messages({"ConfigVisualPanel2.newRule.name=New Rule"})
private void newRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newRuleButtonActionPerformed
NewRuleSetPanel panel;
panel = new NewRuleSetPanel(okButton, cancelButton);
NewRulePanel panel;
panel = new NewRulePanel(okButton, cancelButton);
panel.setEnabled(true);
panel.setVisible(true);
while (true) {
int option = JOptionPane.showOptionDialog(this, panel, "New rule",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
int option = JOptionPane.showOptionDialog(this, panel, Bundle.ConfigVisualPanel2_newRule_name(),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE,
null, new Object[]{okButton, cancelButton}, okButton);
if (option == JOptionPane.OK_OPTION) {
try {
// Save the new rule
@ -477,71 +461,81 @@ final class ConfigVisualPanel2 extends JPanel {
break;
} catch (IOException | NumberFormatException ex) {
JOptionPane.showMessageDialog(this,
ex.getMessage(),
"New rule error",
JOptionPane.ERROR_MESSAGE);
ex.getMessage(),
"New rule error",
JOptionPane.ERROR_MESSAGE);
// let user fix the error
}
} else {
break;
}
}
}
}//GEN-LAST:event_newRuleButtonActionPerformed
@NbBundle.Messages({
"ConfigVisualPanel2.deleteRuleSet=Delete rule ",
"ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule confirmation",
})
"ConfigVisualPanel2.deleteRuleSetConfirmation=Delete rule confirmation",})
private void deleteRuleButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_deleteRuleButtonActionPerformed
int index = rulesTable.getSelectedRow();
if (index != -1) {
String ruleName = (String) rulesTable.getModel().getValueAt(index, 0);
int option = JOptionPane.showOptionDialog(this,
Bundle.ConfigVisualPanel2_deleteRuleSet() + ruleName,
Bundle.ConfigVisualPanel2_deleteRuleSetConfirmation(),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
int option = JOptionPane.showOptionDialog(this,
Bundle.ConfigVisualPanel2_deleteRuleSet() + ruleName,
Bundle.ConfigVisualPanel2_deleteRuleSetConfirmation(),
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null);
if (option == JOptionPane.NO_OPTION) {
return;
}
getFirstRuleSet().getRules().remove(index);
getRuleSetFromCurrentConfig().getRules().remove(index);
updatePanel(configFilename, config);
if (rulesTable.getRowCount() > 0) {
rulesTable.setRowSelectionInterval(0, 0);
rulesTableSelect();
updateForSelectedRule();
}
}
}//GEN-LAST:event_deleteRuleButtonActionPerformed
private void flagEncryptionProgramsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flagEncryptionProgramsCheckBoxActionPerformed
flagEncryptionPrograms = flagEncryptionProgramsCheckBox.isSelected();
toggleEncryptionProgramsRule(flagEncryptionPrograms);
}//GEN-LAST:event_flagEncryptionProgramsCheckBoxActionPerformed
private void rulesTableMouseReleased(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_rulesTableMouseReleased
rulesTableSelect();
updateForSelectedRule();
}//GEN-LAST:event_rulesTableMouseReleased
private void toggleEncryptionProgramsRule(boolean flagEncryptionPrograms) {
private void flagEncryptionProgramsCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_flagEncryptionProgramsCheckBoxActionPerformed
flagEncryptionPrograms = flagEncryptionProgramsCheckBox.isSelected();
setEnabledEncryptionProgramsRule(flagEncryptionPrograms);
}//GEN-LAST:event_flagEncryptionProgramsCheckBoxActionPerformed
private void finalizeImageWriterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_finalizeImageWriterActionPerformed
config.setFinalizeImageWriter(finalizeImageWriter.isSelected());
}//GEN-LAST:event_finalizeImageWriterActionPerformed
/**
* Set the whether the a rule for detecting encryption programs will be
* added to the rules in this config
*
* @param flagEncryptionPrograms true to have encryption programs rule
* added, false otherwise.
*/
private void setEnabledEncryptionProgramsRule(boolean flagEncryptionPrograms) {
if (flagEncryptionPrograms) {
// add the special rule
ImmutablePair<String, LogicalImagerRule> ruleMap = createEncryptionProgramsRule();
appendRow(ruleMap);
appendRow(ruleMap);
} else {
// remove it
int index = ((RulesTableModel) rulesTable.getModel()).findRow(EncryptionProgramsRule.getName());
if (index != -1) {
getFirstRuleSet().getRules().remove(index);
getRuleSetFromCurrentConfig().getRules().remove(index);
updatePanel(configFilename, config);
if (rulesTable.getRowCount() > 0) {
rulesTable.setRowSelectionInterval(0, 0);
rulesTableSelect();
updateForSelectedRule();
}
}
}
}
/*
* Create an encryption programs rule
*/
@ -559,7 +553,6 @@ final class ConfigVisualPanel2 extends JPanel {
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JTextField configFileTextField;
private javax.swing.JLabel daysIncludedLabel;
private javax.swing.JTextField daysIncludedTextField;
private javax.swing.JButton deleteRuleButton;
private javax.swing.JTextField descriptionEditTextField;
private javax.swing.JLabel descriptionLabel;
@ -568,33 +561,34 @@ final class ConfigVisualPanel2 extends JPanel {
private javax.swing.JTextField extensionsTextField;
private javax.swing.JLabel fileSizeLabel;
private javax.swing.JLabel filenamesLabel;
private javax.swing.JScrollPane filenamesScrollPane;
private javax.swing.JTable filenamesTable;
private javax.swing.JCheckBox finalizeImageWriter;
private javax.swing.JCheckBox flagEncryptionProgramsCheckBox;
private javax.swing.JLabel folderNamesLabel;
private javax.swing.JScrollPane folderNamesScrollPane;
private javax.swing.JTable folderNamesTable;
private javax.swing.JLabel fullPathsLabel;
private javax.swing.JScrollPane fullPathsScrollPane;
private javax.swing.JTable fullPathsTable;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane5;
private javax.swing.JScrollPane jScrollPane6;
private javax.swing.JScrollPane jScrollPane7;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JLabel maxSizeLabel;
private javax.swing.JFormattedTextField maxSizeTextField;
private javax.swing.JLabel minSizeLabel;
private javax.swing.JFormattedTextField minSizeTextField;
private javax.swing.JLabel modifiedDateLabel;
private javax.swing.JTextField modifiedWithinTextField;
private javax.swing.JButton newRuleButton;
private javax.swing.JTextField ruleNameEditTextField;
private javax.swing.JLabel ruleNameLabel;
private javax.swing.JLabel ruleSetFileLabel;
private javax.swing.JScrollPane rulesScrollPane;
private javax.swing.JTable rulesTable;
private javax.swing.JCheckBox shouldAlertCheckBox;
private javax.swing.JCheckBox shouldSaveCheckBox;
// End of variables declaration//GEN-END:variables
private LogicalImagerRuleSet getFirstRuleSet() {
private LogicalImagerRuleSet getRuleSetFromCurrentConfig() {
if (config.getRuleSets().isEmpty()) {
List<LogicalImagerRuleSet> ruleSets = new ArrayList<>();
ruleSets.add(new LogicalImagerRuleSet("no-set-name", new ArrayList<>())); // NON-NLS
@ -602,18 +596,25 @@ final class ConfigVisualPanel2 extends JPanel {
}
return config.getRuleSets().get(0);
}
/**
* Update the panel to reflect the rules in the current config
*
* @param configFilePath path of the config file being modified
* @param config contents of the config file being modifed
* @param rowSelectionkey the name of the rule to select by default
*/
private void updatePanel(String configFilePath, LogicalImagerConfig config, String rowSelectionkey) {
configFileTextField.setText(configFilePath);
finalizeImageWriter.setSelected(config.isFinalizeImageWriter());
LogicalImagerRuleSet ruleSet = getFirstRuleSet();
LogicalImagerRuleSet ruleSet = getRuleSetFromCurrentConfig();
flagEncryptionProgramsCheckBox.setSelected(ruleSet.find(EncryptionProgramsRule.getName()) != null);
RulesTableModel rulesTableModel = new RulesTableModel();
int row = 0;
int selectThisRow = 0;
Collections.sort(ruleSet.getRules(), new SortRuleByName());
for (LogicalImagerRule rule : ruleSet.getRules()) {
rulesTableModel.setValueAt(rule.getName(), row, 0);
if (rowSelectionkey != null && rowSelectionkey.equals(rule.getName())) {
@ -628,31 +629,48 @@ final class ConfigVisualPanel2 extends JPanel {
// If there are any rules, select the first one
if (rulesTableModel.getRowCount() > 0) {
rulesTable.setRowSelectionInterval(selectThisRow, selectThisRow);
rulesTableSelect();
updateForSelectedRule();
} else {
updateRuleSetButtons(false);
clearRuleDetails();
updateRuleButtons(false);
}
}
/**
* Private helper method to call updatePanel with no row to select specified
*
* @param configFilePath path of the config file being modified
* @param config contents of the config file being modifed
*/
private void updatePanel(String configFilePath, LogicalImagerConfig config) {
updatePanel(configFilePath, config, null);
}
private void rulesTableSelect() {
/**
* Update the panel to reflect the selected rule
*/
private void updateForSelectedRule() {
int index = rulesTable.getSelectedRow();
if (index != -1) {
String ruleName = (String) rulesTable.getModel().getValueAt(index, 0);
String description = (String) rulesTable.getModel().getValueAt(index, 1);
updateRuleDetails(ruleName, description, config);
updateRuleSetButtons(ruleName.equals(EncryptionProgramsRule.getName()) ? false : true);
updateRuleDetails(ruleName, description);
updateRuleButtons(!ruleName.equals(EncryptionProgramsRule.getName()));
} else {
updateRuleSetButtons(false);
clearRuleDetails();
updateRuleButtons(false);
}
}
private void updateRuleDetails(String ruleName, String description, LogicalImagerConfig config) {
/**
* Update the panel to display details of the specified rule
*
* @param ruleName the name of the rule to display
* @param description the description of the rule to display
*/
private void updateRuleDetails(String ruleName, String description) {
clearRuleDetails();
LogicalImagerRule rule = getFirstRuleSet().find(ruleName);
LogicalImagerRule rule = getRuleSetFromCurrentConfig().find(ruleName);
shouldAlertCheckBox.setSelected(rule.isShouldAlert());
shouldSaveCheckBox.setSelected(rule.isShouldSave());
ruleNameEditTextField.setText(ruleName);
@ -672,18 +690,36 @@ final class ConfigVisualPanel2 extends JPanel {
maxSizeTextField.setText(rule.getMaxFileSize().toString());
}
if (rule.getMinDays() == null) {
daysIncludedTextField.setText("");
modifiedWithinTextField.setText("");
} else {
daysIncludedTextField.setText(Integer.toString(rule.getMinDays()));
modifiedWithinTextField.setText(Integer.toString(rule.getMinDays()));
}
}
/**
* Reset rule details displayed to be blank or default
*/
private void clearRuleDetails() {
ruleNameEditTextField.setText("");
descriptionEditTextField.setText("");
extensionsTextField.setText("");
shouldAlertCheckBox.setSelected(false);
updateExtensions(null);
updateList(filenamesTable, null);
updateList(folderNamesTable, null);
updateList(fullPathsTable, null);
minSizeTextField.setText("");
maxSizeTextField.setText("");
modifiedWithinTextField.setText("");
shouldSaveCheckBox.setSelected(true);
shouldAlertCheckBox.setSelected(false);
}
/**
* Update the extensions displayed
*
* @param extensions the list of extensions to display, null to display
* nothing
*/
private void updateExtensions(List<String> extensions) {
extensionsTextField.setText("");
if (extensions == null) {
@ -691,61 +727,58 @@ final class ConfigVisualPanel2 extends JPanel {
}
String content = "";
boolean first = true;
for (String ext : extensions) {
for (String ext : extensions) {
content += (first ? "" : ",") + ext;
first = false;
}
extensionsTextField.setText(content);
}
private void updateList(javax.swing.JTable jTable, List<String> set) {
/**
* Update a JTable to display a list of Strings
*
* @param jTable the JTable to update
* @param list the list of Strings to display, null to display nothing
*/
private void updateList(javax.swing.JTable jTable, List<String> list) {
SingleColumnTableModel tableModel = new SingleColumnTableModel();
jTable.setTableHeader(null);
if (set == null) {
if (list == null) {
jTable.setModel(tableModel);
return;
}
int row = 0;
for (String s : set) {
for (String s : list) {
tableModel.setValueAt(s, row, 0);
row++;
}
jTable.setModel(tableModel);
}
void setConfiguration(String configFilename, LogicalImagerConfig config, boolean newFile) {
void setConfiguration(String configFilename, LogicalImagerConfig config) {
this.configFilename = configFilename;
this.config = config;
if (newFile) {
initPanel();
}
updatePanel(configFilename, config);
}
private void initPanel() {
configFileTextField.setText("");
rulesTable.setModel(new RulesTableModel());
shouldAlertCheckBox.setSelected(false);
shouldSaveCheckBox.setSelected(true);
ruleNameEditTextField.setText("");
descriptionEditTextField.setText("");
extensionsTextField.setText("");
updateList(filenamesTable, EMPTY_LIST);
updateList(folderNamesTable, EMPTY_LIST);
}
private void updateRow(int index, ImmutablePair<String, LogicalImagerRule> ruleMap) {
getFirstRuleSet().getRules().remove(index);
getFirstRuleSet().getRules().add(ruleMap.getValue());
getRuleSetFromCurrentConfig().getRules().remove(index);
getRuleSetFromCurrentConfig().getRules().add(ruleMap.getValue());
updatePanel(configFilename, config, ruleMap.getKey());
}
private void appendRow(ImmutablePair<String, LogicalImagerRule> ruleMap) {
getFirstRuleSet().getRules().add(ruleMap.getValue());
getRuleSetFromCurrentConfig().getRules().add(ruleMap.getValue());
updatePanel(configFilename, config, ruleMap.getKey());
}
private void updateRuleSetButtons(boolean isRowSelected) {
/**
* Adjust the enabled status of the rule buttons to reflect wether there is
* a currently selected rule which can be modified
*
* @param isRowSelected true if a row is selected, false otherwise
*/
private void updateRuleButtons(boolean isRowSelected) {
newRuleButton.setEnabled(true);
editRuleButton.setEnabled(isRowSelected);
deleteRuleButton.setEnabled(isRowSelected);
@ -756,6 +789,7 @@ final class ConfigVisualPanel2 extends JPanel {
*/
private class SortRuleByName implements Comparator<LogicalImagerRule> {
@Override
public int compare(LogicalImagerRule a, LogicalImagerRule b) {
return a.getName().compareToIgnoreCase(b.getName());
}
@ -766,6 +800,7 @@ final class ConfigVisualPanel2 extends JPanel {
*/
private class RulesTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final List<String> ruleName = new ArrayList<>();
private final List<String> ruleDescription = new ArrayList<>();
private final List<LogicalImagerRule> rule = new ArrayList<>();
@ -773,7 +808,7 @@ final class ConfigVisualPanel2 extends JPanel {
int findRow(String name) {
return ruleName.indexOf(name);
}
@Override
public int getRowCount() {
return ruleName.size();
@ -855,6 +890,8 @@ final class ConfigVisualPanel2 extends JPanel {
*/
private class SingleColumnTableModel extends AbstractTableModel {
private static final long serialVersionUID = 1L;
private final List<String> list = new ArrayList<>();
@Override

View File

@ -0,0 +1,142 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.4" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<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" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="1" max="-2" attributes="0">
<Component id="configLabel" max="32767" attributes="0"/>
<Component id="executableLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="configStatusLabel" min="-2" pref="237" max="-2" attributes="0"/>
<Component id="executableStatusLabel" min="-2" pref="238" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="10" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="descriptionScrollPane" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="saveButton" min="-2" pref="101" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</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"/>
<Component id="descriptionScrollPane" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="saveButton" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="configLabel" max="32767" attributes="0"/>
<Component id="configStatusLabel" min="-2" pref="14" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="executableLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="executableStatusLabel" alignment="3" min="-2" pref="14" max="-2" attributes="0"/>
</Group>
<EmptySpace pref="120" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JButton" name="saveButton">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel3.saveButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="saveButtonActionPerformed"/>
</Events>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Container class="javax.swing.JScrollPane" name="descriptionScrollPane">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextArea" name="descriptionTextArea">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="f0" green="f0" red="f0" type="rgb"/>
</Property>
<Property name="columns" type="int" value="20"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
<Font name="Tahoma" size="11" style="0"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
<Component class="javax.swing.JLabel" name="configLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel3.configLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="configStatusLabel">
</Component>
<Component class="javax.swing.JLabel" name="executableLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel3.executableLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>
<AuxValue name="JavaCodeGenerator_VariableModifier" type="java.lang.Integer" value="0"/>
</AuxValues>
</Component>
<Component class="javax.swing.JLabel" name="executableStatusLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="ConfigVisualPanel3.executableStatusLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,275 @@
/*
* Autopsy
*
* 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.logicalimager.configuration;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import java.awt.Color;
import java.awt.Cursor;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.logicalimager.configuration.CreateLogicalImagerAction.getTskLogicalImagerExe;
/**
* Configuration visual panel 3
*/
class ConfigVisualPanel3 extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(ConfigVisualPanel3.class.getName());
private static final String SAVED_LOGICAL_IMAGER = "SAVED_LOGICAL_IMAGER";
private static final long serialVersionUID = 1L;
private boolean hasBeenSaved = false;
private String configFilename;
private LogicalImagerConfig config;
/**
* Creates new form ConfigVisualPanel3
*/
@NbBundle.Messages({"ConfigVisualPanel3.copyStatus.notSaved=File has not been saved",
"ConfigVisualPanel3.copyStatus.savingInProgress=Saving file, please wait",
"ConfigVisualPanel3.copyStatus.saved=Saved",
"ConfigVisualPanel3.copyStatus.error=Unable to save file"})
ConfigVisualPanel3() {
initComponents();
}
final void resetPanel() {
hasBeenSaved = false;
configStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_notSaved());
executableStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_notSaved());
}
@NbBundle.Messages({
"ConfigVisualPanel3.saveConfigurationFile=Save imager"
})
@Override
public String getName() {
return Bundle.ConfigVisualPanel3_saveConfigurationFile();
}
/**
* Identifies whether the configuration has been saved
*
* @return true if it has been saved, false otherwise
*/
boolean isSaved() {
return hasBeenSaved;
}
/**
* Save the current configuration file and copy the logical imager
* executable to the same location.
*/
@NbBundle.Messages({
"# {0} - configFilename",
"ConfigVisualPanel3.failedToSaveConfigMsg=Failed to save configuration file: {0}",
"# {0} - reason",
"ConfigVisualPanel3.reason=\nReason: ",
"ConfigVisualPanel3.failedToSaveExeMsg=Failed to save tsk_logical_imager.exe file",})
void saveConfigFile() {
boolean saveSuccess = true;
executableStatusLabel.setForeground(Color.BLACK);
configStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_savingInProgress());
executableStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_savingInProgress());
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
GsonBuilder gsonBuilder = new GsonBuilder()
.setPrettyPrinting()
.excludeFieldsWithoutExposeAnnotation()
.disableHtmlEscaping();
Gson gson = gsonBuilder.create();
String toJson = gson.toJson(config);
try {
List<String> lines = Arrays.asList(toJson.split("\\n"));
FileUtils.writeLines(new File(configFilename), "UTF-8", lines, System.getProperty("line.separator")); // NON-NLS
configStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_saved());
} catch (IOException ex) {
saveSuccess = false;
executableStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_error());
executableStatusLabel.setForeground(Color.RED);
JOptionPane.showMessageDialog(this, Bundle.ConfigVisualPanel3_failedToSaveConfigMsg(configFilename)
+ Bundle.ConfigVisualPanel3_reason(ex.getMessage()));
} catch (JsonIOException jioe) {
saveSuccess = false;
executableStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_error());
executableStatusLabel.setForeground(Color.RED);
logger.log(Level.SEVERE, "Failed to save configuration file: " + configFilename, jioe); // NON-NLS
JOptionPane.showMessageDialog(this, Bundle.ConfigVisualPanel3_failedToSaveConfigMsg(configFilename)
+ Bundle.ConfigVisualPanel3_reason(jioe.getMessage()));
}
try {
writeTskLogicalImagerExe(Paths.get(configFilename).getParent());
executableStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_saved());
} catch (IOException ex) {
saveSuccess = false;
executableStatusLabel.setText(Bundle.ConfigVisualPanel3_copyStatus_error());
executableStatusLabel.setForeground(Color.RED);
logger.log(Level.SEVERE, "Failed to save tsk_logical_imager.exe file", ex); // NON-NLS
JOptionPane.showMessageDialog(this, Bundle.ConfigVisualPanel3_failedToSaveExeMsg()
+ Bundle.ConfigVisualPanel3_reason(ex.getMessage()));
}
if (saveSuccess) {
hasBeenSaved = true;
firePropertyChange(SAVED_LOGICAL_IMAGER, false, true); // NON-NLS
}
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
/**
* Write the logical imager executable to the specified location
*
* @param destDir the location to write the logical imager executable to
*
* @throws IOException
*/
private void writeTskLogicalImagerExe(Path destDir) throws IOException {
FileUtils.copyFileToDirectory(getTskLogicalImagerExe(), destDir.toFile());
}
/**
* The name of the event which is sent when the configuration and executable
* have been saved.
*
* @return SAVED_LOGICAL_IMAGER
*/
static String getSavedEventName() {
return SAVED_LOGICAL_IMAGER;
}
/**
* 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() {
javax.swing.JButton saveButton = new javax.swing.JButton();
descriptionScrollPane = new javax.swing.JScrollPane();
descriptionTextArea = new javax.swing.JTextArea();
javax.swing.JLabel configLabel = new javax.swing.JLabel();
configStatusLabel = new javax.swing.JLabel();
javax.swing.JLabel executableLabel = new javax.swing.JLabel();
executableStatusLabel = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(saveButton, org.openide.util.NbBundle.getMessage(ConfigVisualPanel3.class, "ConfigVisualPanel3.saveButton.text")); // NOI18N
saveButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveButtonActionPerformed(evt);
}
});
descriptionTextArea.setEditable(false);
descriptionTextArea.setBackground(new java.awt.Color(240, 240, 240));
descriptionTextArea.setColumns(20);
descriptionTextArea.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
descriptionTextArea.setLineWrap(true);
descriptionTextArea.setRows(5);
descriptionTextArea.setWrapStyleWord(true);
descriptionTextArea.setEnabled(false);
descriptionScrollPane.setViewportView(descriptionTextArea);
org.openide.awt.Mnemonics.setLocalizedText(configLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel3.class, "ConfigVisualPanel3.configLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(executableLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel3.class, "ConfigVisualPanel3.executableLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(executableStatusLabel, org.openide.util.NbBundle.getMessage(ConfigVisualPanel3.class, "ConfigVisualPanel3.executableStatusLabel.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()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(configLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(executableLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(configStatusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 237, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(executableStatusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 238, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 10, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(descriptionScrollPane)
.addGroup(layout.createSequentialGroup()
.addComponent(saveButton, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(saveButton)
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(configLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(configStatusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(executableLabel)
.addComponent(executableStatusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(120, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void saveButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveButtonActionPerformed
saveConfigFile();
}//GEN-LAST:event_saveButtonActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel configStatusLabel;
private javax.swing.JScrollPane descriptionScrollPane;
private javax.swing.JTextArea descriptionTextArea;
private javax.swing.JLabel executableStatusLabel;
// End of variables declaration//GEN-END:variables
/**
* Set the information necessary to save the configuration
*
* @param configFile the path to the json configuration file
* @param config the configuration to save
*/
@NbBundle.Messages({
"# {0} - configurationLocation",
"ConfigVisualPanel3.description.text=Press Save to write the imaging tool and configuration file to the destination.\nDestination: {0}"
})
void setConfigInfoForSaving(String configFile, LogicalImagerConfig config) {
this.configFilename = configFile;
this.config = config;
descriptionTextArea.setText(Bundle.ConfigVisualPanel3_description_text(FilenameUtils.getFullPath(configFilename)));
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -52,13 +52,13 @@ final class ConfigWizardPanel1 implements WizardDescriptor.ValidatingPanel<Wizar
component.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals("UPDATE_UI")) { // NON-NLS
if (evt.getPropertyName().equals(ConfigVisualPanel1.getUpdateEventName())) { // NON-NLS
valid = component.isPanelValid();
fireChangeEvent();
}
}
});
}
return component;
}
@ -79,7 +79,7 @@ final class ConfigWizardPanel1 implements WizardDescriptor.ValidatingPanel<Wizar
// use ChangeSupport to implement add/removeChangeListener below.
// WizardDescriptor.ERROR/WARNING/INFORMATION_MESSAGE will also be useful.
}
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
/**
@ -130,9 +130,8 @@ final class ConfigWizardPanel1 implements WizardDescriptor.ValidatingPanel<Wizar
@Override
public void storeSettings(WizardDescriptor wiz) {
// use wiz.putProperty to remember current panel state
wiz.putProperty("configFilename", component.getConfigFilename()); // NON-NLS
wiz.putProperty("configFilename", component.getConfigPath()); // NON-NLS
wiz.putProperty("config", component.getConfig()); // NON-NLS
wiz.putProperty("newFile", component.isNewFile()); // NON-NLS
}
@Override

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -18,32 +18,15 @@
*/
package org.sleuthkit.autopsy.logicalimager.configuration;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonIOException;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeListener;
import org.apache.commons.io.FileUtils;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import static org.sleuthkit.autopsy.logicalimager.configuration.ConfigureLogicalImager.getTskLogicalImagerExe;
/**
* Configuration Wizard Panel 2
*/
final class ConfigWizardPanel2 implements WizardDescriptor.Panel<WizardDescriptor> {
private static final Logger LOGGER = Logger.getLogger(ConfigWizardPanel2.class.getName());
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
@ -87,51 +70,13 @@ final class ConfigWizardPanel2 implements WizardDescriptor.Panel<WizardDescripto
// use wiz.getProperty to retrieve previous panel state
configFilename = (String) wiz.getProperty("configFilename"); // NON-NLS
config = (LogicalImagerConfig) wiz.getProperty("config"); // NON-NLS
component.setConfiguration(configFilename, config, (boolean) wiz.getProperty("newFile"));
component.setConfiguration(configFilename, config);
}
@Override
public void storeSettings(WizardDescriptor wiz) {
// use wiz.putProperty to remember current panel state
}
@NbBundle.Messages({
"# {0} - configFilename",
"ConfigWizardPanel2.failedToSaveConfigMsg=Failed to save configuration file: {0}",
"# {0} - reason",
"ConfigWizardPanel2.reason=\nReason: ",
"ConfigWizardPanel2.failedToSaveExeMsg=Failed to save tsk_logical_imager.exe file",
})
void saveConfigFile() {
GsonBuilder gsonBuilder = new GsonBuilder()
.setPrettyPrinting()
.excludeFieldsWithoutExposeAnnotation()
.disableHtmlEscaping();
Gson gson = gsonBuilder.create();
String toJson = gson.toJson(config);
try {
List<String> lines = Arrays.asList(toJson.split("\\n"));
FileUtils.writeLines(new File(configFilename), "UTF-8", lines, System.getProperty("line.separator")); // NON-NLS
} catch (IOException ex) {
JOptionPane.showMessageDialog(component, Bundle.ConfigWizardPanel2_failedToSaveConfigMsg(configFilename)
+ Bundle.ConfigWizardPanel2_reason(ex.getMessage()));
} catch (JsonIOException jioe) {
LOGGER.log(Level.SEVERE, "Failed to save configuration file: " + configFilename, jioe); // NON-NLS
JOptionPane.showMessageDialog(component, Bundle.ConfigWizardPanel2_failedToSaveConfigMsg(configFilename)
+ Bundle.ConfigWizardPanel2_reason(jioe.getMessage()));
}
try {
writeTskLogicalImagerExe(Paths.get(configFilename).getParent());
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, "Failed to save tsk_logical_imager.exe file", ex); // NON-NLS
JOptionPane.showMessageDialog(component, Bundle.ConfigWizardPanel2_failedToSaveExeMsg()
+ Bundle.ConfigWizardPanel2_reason(ex.getMessage()));
}
}
private void writeTskLogicalImagerExe(Path destDir) throws IOException {
FileUtils.copyFileToDirectory(getTskLogicalImagerExe(), destDir.toFile());
}
@Override
public void addChangeListener(ChangeListener cl) {

View File

@ -0,0 +1,106 @@
/*
* Autopsy
*
* 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.logicalimager.configuration;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.openide.WizardDescriptor;
import org.openide.util.HelpCtx;
/**
* Configuration Wizard Panel 3
*/
final class ConfigWizardPanel3 implements WizardDescriptor.Panel<WizardDescriptor> {
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
private ConfigVisualPanel3 component;
@Override
public ConfigVisualPanel3 getComponent() {
if (component == null) {
component = new ConfigVisualPanel3();
component.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getPropertyName().equals(ConfigVisualPanel3.getSavedEventName())) { // NON-NLS
fireChangeEvent();
}
}
});
}
return component;
}
@Override
public HelpCtx getHelp() {
return HelpCtx.DEFAULT_HELP;
}
@Override
public void readSettings(WizardDescriptor wiz) {
String configFilename = (String) wiz.getProperty("configFilename"); // NON-NLS
LogicalImagerConfig config = (LogicalImagerConfig) wiz.getProperty("config"); // NON-NLS
component.setConfigInfoForSaving(configFilename, config);
component.resetPanel();
}
@Override
public void storeSettings(WizardDescriptor data) {
//no settings to store
}
@Override
public boolean isValid() {
return component.isSaved();
}
/**
* Fire an envent to indicate that state of the wizard panel has changed
*/
private void fireChangeEvent() {
Iterator<ChangeListener> it;
synchronized (listeners) {
it = new HashSet<>(listeners).iterator();
}
ChangeEvent ev = new ChangeEvent(this);
while (it.hasNext()) {
it.next().stateChanged(ev);
}
}
@Override
public void addChangeListener(ChangeListener cl) {
synchronized (listeners) {
listeners.add(cl);
}
}
@Override
public void removeChangeListener(ChangeListener cl) {
synchronized (listeners) {
listeners.remove(cl);
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 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.logicalimager.configuration;
import java.awt.Component;
import java.awt.Dialog;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
@ -38,28 +39,25 @@ import static org.sleuthkit.autopsy.coreutils.PlatformUtil.getInstallModulesPath
/**
* Configuration Logical Imager
*/
@ActionID(
category = "Tools",
id = "org.sleuthkit.autopsy.configurelogicalimager.ConfigureLogicalImager"
)
@ActionRegistration(displayName = "#CTL_ConfigureLogicalImager", lazy = false)
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.logicalimager.configuration.CreateLogicalImagerAction")
@ActionRegistration(displayName = "#CTL_CreateLogicalImagerAction", lazy = false)
@ActionReference(path = "Menu/Tools", position = 2000, separatorBefore = 1999)
@Messages("CTL_ConfigureLogicalImager=Create Logical Imager")
public final class ConfigureLogicalImager extends CallableSystemAction {
@Messages("CTL_CreateLogicalImagerAction=Create Logical Imager")
public final class CreateLogicalImagerAction extends CallableSystemAction {
private static final String DISPLAY_NAME = Bundle.CTL_ConfigureLogicalImager();
private static final String DISPLAY_NAME = Bundle.CTL_CreateLogicalImagerAction();
private static final String TSK_LOGICAL_IMAGER_DIR = "tsk_logical_imager"; // NON-NLS
private static final String TSK_LOGICAL_IMAGER_EXE = "tsk_logical_imager.exe"; // NON-NLS
@NbBundle.Messages({
"ConfigureLogicalImager.title=Configure Logical Imager"
"CreateLogicalImagerAction.title=Create Logical Imager"
})
@Override
public void performAction() {
List<WizardDescriptor.Panel<WizardDescriptor>> panels = new ArrayList<>();
panels.add(new ConfigWizardPanel1());
panels.add(new ConfigWizardPanel2());
panels.add(new ConfigWizardPanel3());
String[] steps = new String[panels.size()];
for (int i = 0; i < panels.size(); i++) {
Component c = panels.get(i).getComponent();
@ -77,12 +75,9 @@ public final class ConfigureLogicalImager extends CallableSystemAction {
WizardDescriptor wiz = new WizardDescriptor(new WizardDescriptor.ArrayIterator<>(panels));
// {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
wiz.setTitleFormat(new MessageFormat("{0}")); // NON-NLS
wiz.setTitle(Bundle.ConfigureLogicalImager_title());
if ((DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) &&
(panels.get(1) instanceof ConfigWizardPanel2)) {
ConfigWizardPanel2 panel = (ConfigWizardPanel2) panels.get(1);
panel.saveConfigFile();
}
wiz.setTitle(Bundle.CreateLogicalImagerAction_title());
Dialog dialog = DialogDisplayer.getDefault().createDialog(wiz);
dialog.setVisible(true);
}
@Override
@ -100,7 +95,7 @@ public final class ConfigureLogicalImager extends CallableSystemAction {
File tskLogicalImagerExe = getTskLogicalImagerExe();
return tskLogicalImagerExe.exists();
}
static public File getTskLogicalImagerExe() {
String installModulesPath = getInstallModulesPath();
File tskLogicalImagerExe = new File(installModulesPath + File.separator + TSK_LOGICAL_IMAGER_DIR + File.separator + TSK_LOGICAL_IMAGER_EXE);

View File

@ -0,0 +1,40 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.logicalimager.configuration;
import java.text.NumberFormat;
import java.text.ParseException;
import javax.swing.text.NumberFormatter;
/**
* Number formatter which will reset to being a null value when an invalid value
* is entered
*/
final class DefaultToEmptyNumberFormatter extends NumberFormatter {
private static final long serialVersionUID = 1L;
/**
* Create a DefaultToEmptyNumberFormatter
*
* @param format the format for the numbers
*/
DefaultToEmptyNumberFormatter(NumberFormat format) {
super(format);
}
@Override
public Object stringToValue(String string)
throws ParseException {
Object returnValue = null;
try {
returnValue = super.stringToValue(string);
} catch (ParseException ignored) {
//reset value to being empty since invalid value was entered
}
return returnValue;
}
}

View File

@ -16,23 +16,31 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="shouldSaveCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="jSeparator2" max="32767" attributes="0"/>
<Component id="jSeparator1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ruleNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="descriptionLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fullPathsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ruleNameTextField" alignment="0" pref="519" max="32767" attributes="0"/>
<Component id="descriptionTextField" alignment="0" max="32767" attributes="0"/>
<Component id="fullPathsScrollPane" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="ruleNameLabel" linkSize="1" alignment="0" max="32767" attributes="0"/>
<Component id="fullPathsLabel" linkSize="1" alignment="0" max="32767" attributes="0"/>
<Component id="jLabel1" linkSize="1" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ruleNameTextField" linkSize="2" alignment="0" min="-2" pref="648" max="-2" attributes="0"/>
<Component id="descriptionTextField" linkSize="2" alignment="0" min="-2" pref="648" max="-2" attributes="0"/>
<Component id="fullPathsScrollPane" linkSize="2" min="-2" pref="648" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="shouldSaveCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -42,7 +50,7 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="ruleNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ruleNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
@ -50,20 +58,26 @@
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="descriptionTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="descriptionLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="jLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="fullPathsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="167" max="32767" attributes="0"/>
<EmptySpace min="0" pref="115" max="32767" attributes="0"/>
</Group>
<Component id="fullPathsScrollPane" max="32767" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="shouldSaveCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
@ -77,6 +91,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.shouldSaveCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="shouldSaveCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="shouldAlertCheckBox">
<Properties>
@ -87,6 +104,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="shouldAlertCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="fullPathsLabel">
<Properties>
@ -96,39 +116,49 @@
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.fullPathsLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="descriptionTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.descriptionTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="descriptionLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.descriptionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ruleNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.ruleNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="ruleNameTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.ruleNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="fullPathsScrollPane">
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
<Component class="javax.swing.JSeparator" name="jSeparator1">
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator2">
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditFullPathsRulePanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,6 +28,10 @@ import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.openide.util.NbBundle;
@ -40,7 +44,7 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
private JButton okButton;
private JButton cancelButton;
private final JTextArea fullPathsTextArea;
/**
* Creates new form EditFullPathsRulePanel
*/
@ -49,25 +53,60 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
})
EditFullPathsRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule, boolean editing) {
initComponents();
if (editing) {
ruleNameTextField.setEnabled(!editing);
}
this.setRule(ruleName, rule);
this.setButtons(okButton, cancelButton);
fullPathsTextArea = new JTextArea();
initTextArea(fullPathsScrollPane, fullPathsTextArea);
setTextArea(fullPathsTextArea, rule.getFullPaths());
EditRulePanel.setTextFieldPrompts(fullPathsTextArea,
EditRulePanel.setTextFieldPrompts(fullPathsTextArea,
"<html>" + Bundle.EditFullPathsRulePanel_example() + "<br>/Program Files/Common Files/system/wab32.dll<br>/Windows/System32/1033/VsGraphicsResources.dll</html>"); // NON-NLS
ruleNameTextField.requestFocus();
addDocumentListeners();
validate();
repaint();
repaint();
}
/**
* Update the OK button when contents of a field change
*/
private void addDocumentListeners() {
SwingUtilities.invokeLater(() -> {
setOkButton(); //ensure initial state before listeners added is correct
});
DocumentListener docListener;
docListener = new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
setOkButton();
}
@Override
public void insertUpdate(DocumentEvent e) {
setOkButton();
}
@Override
public void removeUpdate(DocumentEvent e) {
setOkButton();
}
};
ruleNameTextField.getDocument().addDocumentListener(docListener);
fullPathsTextArea.getDocument().addDocumentListener(docListener);
}
/**
* Initialize the text area and the scroll pane viewing it
*
* @param pane the JScrollPane which will be viewing the JTextArea
* @param textArea the JTextArea being initialized
*/
private void initTextArea(JScrollPane pane, JTextArea textArea) {
textArea.setColumns(20);
textArea.setRows(5);
@ -83,7 +122,7 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
}
e.consume();
}
}
}
});
}
@ -100,27 +139,41 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
shouldAlertCheckBox = new javax.swing.JCheckBox();
fullPathsLabel = new javax.swing.JLabel();
descriptionTextField = new javax.swing.JTextField();
descriptionLabel = new javax.swing.JLabel();
ruleNameLabel = new javax.swing.JLabel();
ruleNameTextField = new javax.swing.JTextField();
fullPathsScrollPane = new javax.swing.JScrollPane();
jSeparator1 = new javax.swing.JSeparator();
jSeparator2 = new javax.swing.JSeparator();
jLabel1 = new javax.swing.JLabel();
jLabel2 = new javax.swing.JLabel();
shouldSaveCheckBox.setSelected(true);
org.openide.awt.Mnemonics.setLocalizedText(shouldSaveCheckBox, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.shouldSaveCheckBox.text")); // NOI18N
shouldSaveCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
shouldSaveCheckBoxActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(shouldAlertCheckBox, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.shouldAlertCheckBox.text")); // NOI18N
shouldAlertCheckBox.setActionCommand(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.shouldAlertCheckBox.actionCommand")); // NOI18N
shouldAlertCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
shouldAlertCheckBoxActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(fullPathsLabel, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.fullPathsLabel.text")); // NOI18N
fullPathsLabel.setToolTipText(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.fullPathsLabel.toolTipText")); // NOI18N
descriptionTextField.setText(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.descriptionTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(descriptionLabel, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.descriptionLabel.text")); // NOI18N
fullPathsLabel.setPreferredSize(new java.awt.Dimension(112, 14));
org.openide.awt.Mnemonics.setLocalizedText(ruleNameLabel, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.ruleNameLabel.text")); // NOI18N
ruleNameLabel.setPreferredSize(new java.awt.Dimension(112, 14));
ruleNameTextField.setText(org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.ruleNameTextField.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.jLabel1.text")); // NOI18N
jLabel1.setPreferredSize(new java.awt.Dimension(112, 14));
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(EditFullPathsRulePanel.class, "EditFullPathsRulePanel.jLabel2.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@ -129,51 +182,79 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(shouldSaveCheckBox)
.addComponent(shouldAlertCheckBox)
.addComponent(jSeparator2)
.addComponent(jSeparator1)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ruleNameLabel)
.addComponent(descriptionLabel)
.addComponent(fullPathsLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ruleNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 519, Short.MAX_VALUE)
.addComponent(descriptionTextField)
.addComponent(fullPathsScrollPane))))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(ruleNameLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(fullPathsLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(0, 0, 0)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 648, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(descriptionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 648, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(fullPathsScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 648, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(shouldSaveCheckBox)
.addComponent(shouldAlertCheckBox)
.addComponent(jLabel2))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {fullPathsLabel, jLabel1, ruleNameLabel});
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {descriptionTextField, fullPathsScrollPane, ruleNameTextField});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGap(8, 8, 8)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(ruleNameLabel)
.addComponent(ruleNameLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ruleNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(descriptionTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(descriptionLabel))
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(fullPathsLabel)
.addGap(0, 167, Short.MAX_VALUE))
.addComponent(fullPathsLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 115, Short.MAX_VALUE))
.addComponent(fullPathsScrollPane))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(shouldAlertCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(shouldSaveCheckBox)
.addGap(3, 3, 3)
.addComponent(shouldAlertCheckBox)
.addContainerGap())
);
}// </editor-fold>//GEN-END:initComponents
private void shouldSaveCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_shouldSaveCheckBoxActionPerformed
setOkButton();
}//GEN-LAST:event_shouldSaveCheckBoxActionPerformed
private void shouldAlertCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_shouldAlertCheckBoxActionPerformed
setOkButton();
}//GEN-LAST:event_shouldAlertCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel descriptionLabel;
private javax.swing.JTextField descriptionTextField;
private javax.swing.JLabel fullPathsLabel;
private javax.swing.JScrollPane fullPathsScrollPane;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JSeparator jSeparator2;
private javax.swing.JLabel ruleNameLabel;
private javax.swing.JTextField ruleNameTextField;
private javax.swing.JCheckBox shouldAlertCheckBox;
@ -184,9 +265,9 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
* Sets whether or not the OK button should be enabled based upon other UI
* elements
*/
private void setOkButton() {
void setOkButton() {
if (this.okButton != null) {
this.okButton.setEnabled(true);
this.okButton.setEnabled(!StringUtils.isBlank(ruleNameTextField.getText()) && !StringUtils.isBlank(fullPathsTextArea.getText()) && (shouldAlertCheckBox.isSelected() || shouldSaveCheckBox.isSelected()));
}
}
@ -224,9 +305,14 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
JOptionPane pane = getOptionPane(cancelButton);
pane.setValue(cancelButton);
});
this.setOkButton();
}
/**
* Set the name description and should alert / should save checkboxes
*
* @param ruleName the name of the rule
* @param rule the LogicalImagerRule
*/
private void setRule(String ruleName, LogicalImagerRule rule) {
ruleNameTextField.setText(ruleName);
descriptionTextField.setText(rule.getDescription());
@ -234,17 +320,31 @@ final class EditFullPathsRulePanel extends javax.swing.JPanel {
shouldSaveCheckBox.setSelected(rule.isShouldSave());
}
private void setTextArea(JTextArea textArea, List<String> set) {
/**
* Set the text of a text area to contain the contents of the list each on
* its own line
*
* @param textArea the text area to set the contents of
* @param list the list of strings to display in the text area
*/
private void setTextArea(JTextArea textArea, List<String> list) {
String text = "";
for (String s : set) {
for (String s : list) {
text += s + System.getProperty("line.separator"); // NON-NLS
}
textArea.setText(text);
}
/**
* Convert the contents of this panel to a rule and return it as well as its
* name.
*
* @return an ImmutablePair containing the name of the rule and the rule
*
* @throws IOException
*/
@NbBundle.Messages({
"EditFullPathsRulePanel.fullPaths=Full paths",
})
"EditFullPathsRulePanel.fullPaths=Full paths",})
ImmutablePair<String, LogicalImagerRule> toRule() throws IOException {
List<String> fullPaths = EditRulePanel.validateTextList(fullPathsTextArea, Bundle.EditFullPathsRulePanel_fullPaths());
String ruleName = EditRulePanel.validRuleName(ruleNameTextField.getText());

View File

@ -1,10 +1,6 @@
<?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="buttonGroup">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -21,61 +17,68 @@
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jSeparator2" alignment="0" max="32767" attributes="0"/>
<Component id="jSeparator1" alignment="0" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="extensionsRadioButton" min="-2" max="-2" attributes="0"/>
<Component id="filenamesRadioButton" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ruleNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="descriptionLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="extensionsLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="filenamesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="folderNamesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fileSizeLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="modifiedDateLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="folderNamesScrollPane" alignment="1" max="32767" attributes="0"/>
<Component id="filenamesScrollPane" alignment="1" max="32767" attributes="0"/>
<Component id="extensionsTextField" alignment="1" max="32767" attributes="0"/>
<Component id="descriptionTextField" alignment="1" max="32767" attributes="0"/>
<Component id="ruleNameTextField" alignment="1" max="32767" attributes="0"/>
<Component id="shouldAlertCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="shouldSaveCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="fileNamesCheckbox" linkSize="2" alignment="0" min="-2" pref="112" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="1" max="-2" attributes="0">
<Component id="modifiedWithinCheckbox" linkSize="2" max="32767" attributes="0"/>
<Component id="maxSizeCheckbox" linkSize="2" max="32767" attributes="0"/>
</Group>
<Component id="jLabel1" alignment="0" min="-2" pref="120" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
<Group type="102" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
<Component id="extensionsCheckbox" linkSize="2" alignment="0" max="32767" attributes="0"/>
<Component id="ruleNameLabel" linkSize="2" alignment="0" max="32767" attributes="0"/>
<Component id="descriptionLabel" linkSize="2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="minSizeCheckbox" linkSize="2" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="folderNamesCheckbox" linkSize="2" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ruleNameTextField" alignment="1" max="32767" attributes="0"/>
<Component id="descriptionTextField" alignment="1" max="32767" attributes="0"/>
<Component id="extensionsTextField" alignment="1" max="32767" attributes="0"/>
<Component id="folderNamesScrollPane" max="32767" attributes="0"/>
<Component id="filenamesScrollPane" alignment="1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="shouldSaveCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="108" pref="108" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="minDaysTextField" max="32767" attributes="0"/>
<Component id="minSizeLabel" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="minSizeTextField" min="-2" pref="63" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="maxSizeLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="maxSizeTextField" min="-2" pref="63" max="-2" attributes="0"/>
<Component id="fileNamesInfoLabel" min="-2" max="-2" attributes="0"/>
<Component id="extensionsInfoLabel" min="-2" max="-2" attributes="0"/>
<Group type="103" alignment="0" groupAlignment="1" attributes="0">
<Component id="jLabel2" min="-2" pref="522" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="userFolderNote" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Component id="minSizeTextField" linkSize="1" min="-2" pref="63" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="minSizeUnitsCombobox" linkSize="3" min="-2" pref="110" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="1" attributes="0">
<Component id="modifiedWithinTextField" linkSize="1" min="-2" pref="63" max="-2" attributes="0"/>
<Component id="maxSizeTextField" linkSize="1" min="-2" pref="63" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="maxSizeUnitsCombobox" linkSize="3" min="-2" pref="110" max="-2" attributes="0"/>
<Component id="daysIncludedLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
<Component id="daysIncludedLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="11" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace min="0" pref="236" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -85,69 +88,79 @@
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="ruleNameLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="ruleNameTextField" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="descriptionLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="descriptionTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="descriptionTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="descriptionLabel" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="extensionsTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="extensionsLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="extensionsRadioButton" alignment="2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="extensionsTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="extensionsCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="extensionsInfoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="filenamesScrollPane" alignment="0" pref="70" max="32767" attributes="0"/>
<Component id="filenamesScrollPane" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="2" attributes="0">
<Component id="filenamesLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="filenamesRadioButton" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="fileNamesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="fileNamesInfoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="folderNamesLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="folderNamesScrollPane" alignment="0" pref="71" max="32767" attributes="0"/>
<Component id="folderNamesScrollPane" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Component id="folderNamesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="fileSizeLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="minSizeLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="minSizeTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="maxSizeLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="maxSizeTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="userFolderNote" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="minSizeTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="minSizeCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="minSizeUnitsCombobox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="6" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="maxSizeTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="maxSizeCheckbox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="maxSizeUnitsCombobox" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="2" attributes="0">
<Component id="modifiedDateLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="daysIncludedLabel" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="minDaysTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="modifiedWithinTextField" alignment="2" min="-2" max="-2" attributes="0"/>
<Component id="modifiedWithinCheckbox" alignment="2" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="shouldSaveCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="shouldAlertCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="modifiedDateLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.modifiedDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="daysIncludedLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -162,6 +175,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.shouldSaveCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="shouldSaveCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="shouldAlertCheckBox">
<Properties>
@ -172,151 +188,227 @@
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.shouldAlertCheckBox.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="extensionsLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.extensionsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="shouldAlertCheckBoxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JTextField" name="extensionsTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.extensionsTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="filenamesLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.filenamesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="folderNamesLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.folderNamesLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="fileSizeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.fileSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="descriptionTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.descriptionTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="descriptionLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.descriptionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="ruleNameLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.ruleNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="ruleNameTextField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.ruleNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="ruleNameTextField">
</Component>
<Container class="javax.swing.JScrollPane" name="filenamesScrollPane">
<Properties>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.filenamesScrollPane.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
<Container class="javax.swing.JScrollPane" name="folderNamesScrollPane">
<Properties>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
<Component class="javax.swing.JLabel" name="minSizeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.minSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JFormattedTextField" name="minSizeTextField">
<Properties>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
<Format format="#,###; " subtype="-1" type="0"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.minSizeTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="maxSizeLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.maxSizeLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.text.DefaultFormatterFactory(new DefaultToEmptyNumberFormatter(new java.text.DecimalFormat(&quot;#,###; &quot;)))" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JFormattedTextField" name="maxSizeTextField">
<Properties>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
<Format format="#,###; " subtype="-1" type="0"/>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.text.DefaultFormatterFactory(new DefaultToEmptyNumberFormatter(new java.text.DecimalFormat(&quot;#,###; &quot;)))" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JFormattedTextField" name="modifiedWithinTextField">
<Properties>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.text.DefaultFormatterFactory(new DefaultToEmptyNumberFormatter(new java.text.DecimalFormat(&quot;#,###; &quot;)))" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="userFolderNote">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/info-icon-16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.maxSizeTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.userFolderNote.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JFormattedTextField" name="minDaysTextField">
<Component class="javax.swing.JCheckBox" name="minSizeCheckbox">
<Properties>
<Property name="formatterFactory" type="javax.swing.JFormattedTextField$AbstractFormatterFactory" editor="org.netbeans.modules.form.editors.AbstractFormatterFactoryEditor">
<Format format="####; " subtype="-1" type="0"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="extensionsRadioButton">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup"/>
</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/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.extensionsRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.minSizeCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.extensionsRadioButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="extensionsRadioButtonActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="minSizeCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="filenamesRadioButton">
<Component class="javax.swing.JCheckBox" name="maxSizeCheckbox">
<Properties>
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
<ComponentRef name="buttonGroup"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.filenamesRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.maxSizeCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.filenamesRadioButton.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="filenamesRadioButtonActionPerformed"/>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="maxSizeCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="modifiedWithinCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.modifiedWithinCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="modifiedWithinCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="folderNamesCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.folderNamesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="folderNamesCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="fileNamesCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.fileNamesCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="fileNamesCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="extensionsCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.extensionsCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 23]"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="extensionsCheckboxActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JComboBox" name="minSizeUnitsCombobox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;String&gt;(new String[] { Bundle.EditNonFullPathsRulePanel_units_bytes(), Bundle.EditNonFullPathsRulePanel_units_kilobytes(), Bundle.EditNonFullPathsRulePanel_units_megabytes(), Bundle.EditNonFullPathsRulePanel_units_gigabytes()})" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JComboBox" name="maxSizeUnitsCombobox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;String&gt;(new String[] { Bundle.EditNonFullPathsRulePanel_units_bytes(), Bundle.EditNonFullPathsRulePanel_units_kilobytes(), Bundle.EditNonFullPathsRulePanel_units_megabytes(), Bundle.EditNonFullPathsRulePanel_units_gigabytes()})" type="code"/>
</Property>
<Property name="enabled" type="boolean" value="false"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="&lt;String&gt;"/>
</AuxValues>
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator1">
</Component>
<Component class="javax.swing.JSeparator" name="jSeparator2">
</Component>
<Component class="javax.swing.JLabel" name="descriptionLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.descriptionLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[112, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.jLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="jLabel1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="extensionsInfoLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/info-icon-16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.extensionsInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="fileNamesInfoLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/images/info-icon-16.png"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="EditNonFullPathsRulePanel.fileNamesInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,17 +38,20 @@ import org.sleuthkit.autopsy.corecomponents.TextPrompt;
*/
final class EditRulePanel extends JPanel {
private EditFullPathsRulePanel editFullPathsRulePanel = null;
private EditNonFullPathsRulePanel editNonFullPathsRulePanel = null;
private static final long serialVersionUID = 1L;
private final EditFullPathsRulePanel editFullPathsRulePanel;
private final EditNonFullPathsRulePanel editNonFullPathsRulePanel;
/**
* Creates new form EditRulePanel
*/
EditRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule) {
EditRulePanel(JButton okButton, JButton cancelButton, String ruleName, LogicalImagerRule rule) {
if (rule.getFullPaths() != null && rule.getFullPaths().size() > 0) {
editFullPathsRulePanel = new EditFullPathsRulePanel(okButton, cancelButton, ruleName, rule, true);
editNonFullPathsRulePanel = null;
} else {
editNonFullPathsRulePanel = new EditNonFullPathsRulePanel(okButton, cancelButton, ruleName, rule, true);
editFullPathsRulePanel = null;
}
}
@ -66,10 +69,10 @@ final class EditRulePanel extends JPanel {
ruleMap = editFullPathsRulePanel.toRule();
} else {
ruleMap = editNonFullPathsRulePanel.toRule();
}
}
return ruleMap;
}
static void setTextFieldPrompts(JTextComponent textField, String text) {
/**
* Add text prompt to the text field.
@ -78,41 +81,45 @@ final class EditRulePanel extends JPanel {
if (textField instanceof JTextArea) {
textPrompt = new TextPrompt(text, textField, BorderLayout.NORTH);
} else {
textPrompt = new TextPrompt(text, textField);
textPrompt = new TextPrompt(text, textField);
}
/**
* Sets the foreground color and transparency of the text prompt.
*/
textPrompt.setForeground(Color.LIGHT_GRAY);
textPrompt.changeAlpha(0.9f); // Mostly opaque
}
@NbBundle.Messages({
"EditRulePanel.validateRuleNameExceptionMsg=Rule name cannot be empty"
})
"EditRulePanel.emptyRuleName.message=Rule name cannot be empty",
"# {0} - ruleName",
"EditRulePanel.reservedRuleName.message=Rule name \"{0}\" is reserved for use with a predefined rule"})
static String validRuleName(String name) throws IOException {
if (name.isEmpty()) {
throw new IOException(Bundle.EditRulePanel_validateRuleNameExceptionMsg());
throw new IOException(Bundle.EditRulePanel_emptyRuleName_message());
}
if (name.equals(EncryptionProgramsRule.getName())) {
throw new IOException(Bundle.EditRulePanel_reservedRuleName_message(name));
}
//TODO JIRA-5239 check if rule name exists already
return name;
}
@NbBundle.Messages({
"# {0} - fieldName",
"EditRulePanel.blankLineException={0} cannot have a blank line",
})
"EditRulePanel.blankLineException={0} cannot have a blank line",})
static List<String> validateTextList(JTextArea textArea, String fieldName) throws IOException {
if (isBlank(textArea.getText())) {
return null;
}
List<String> list = new ArrayList<>();
for (String line : textArea.getText().split("\\n")) { // NON-NLS
line = strip(line);
if (line.isEmpty()) {
String strippedLine = strip(line);
if (strippedLine.isEmpty()) {
throw new IOException(Bundle.EditRulePanel_blankLineException(fieldName));
}
list.add(line);
list.add(strippedLine);
}
if (list.isEmpty()) {
return null;

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -23,7 +23,7 @@ import java.util.List;
import org.openide.util.NbBundle;
/**
* Encryption programs rule
* Encryption programs rule
*/
@NbBundle.Messages({
"EncryptionProgramsRule.encryptionProgramsRuleName=Encryption Programs",
@ -34,14 +34,15 @@ final class EncryptionProgramsRule {
private static final String ENCRYPTION_PROGRAMS_RULE_NAME = Bundle.EncryptionProgramsRule_encryptionProgramsRuleName();
private static final String ENCRYPTION_PROGRAMS_RULE_DESCRIPTION = Bundle.EncryptionProgramsRule_encryptionProgramsRuleDescription();
private static final List<String> FILENAMES = new ArrayList<>();
private EncryptionProgramsRule() {}
// TODO: Add more files here
private EncryptionProgramsRule() {
//private no arg constructor intentionally blank
}
static {
// Truecrypt
FILENAMES.add("truecrypt.exe"); // NON-NLS
// AxCrypt
FILENAMES.add("AxCrypt.exe"); // NON-NLS
@ -62,7 +63,7 @@ final class EncryptionProgramsRule {
FILENAMES.add("gpgsm.exe"); // NON-NLS
FILENAMES.add("gpgtar.exe"); // NON-NLS
FILENAMES.add("gpgv.exe"); // NON-NLS
// Symantec Encryption Desktop aka PGP
FILENAMES.add("PGP Viewer.exe"); // NON-NLS
FILENAMES.add("PGPcbt64.exe"); // NON-NLS
@ -87,7 +88,7 @@ final class EncryptionProgramsRule {
static String getDescription() {
return ENCRYPTION_PROGRAMS_RULE_DESCRIPTION;
}
static List<String> getFilenames() {
return FILENAMES;
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -35,19 +35,19 @@ class LogicalImagerConfig {
private String version;
@SerializedName("finalize-image-writer")
@Expose(serialize = true)
@Expose(serialize = true)
private boolean finalizeImageWriter;
@SerializedName("rule-sets")
@Expose(serialize = true)
@Expose(serialize = true)
private List<LogicalImagerRuleSet> ruleSets;
LogicalImagerConfig() {
this.version = CURRENT_VERSION;
this.finalizeImageWriter = false;
this.ruleSets = new ArrayList<>();
}
LogicalImagerConfig(
boolean finalizeImageWriter,
List<LogicalImagerRuleSet> ruleSets
@ -93,5 +93,5 @@ class LogicalImagerConfig {
void setRuleSet(List<LogicalImagerRuleSet> ruleSets) {
this.ruleSets = ruleSets;
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,8 +38,7 @@ import org.openide.util.NbBundle;
"LogicalImagerConfigDeserializer.missingRuleSetException=Missing rule-set",
"# {0} - key",
"LogicalImagerConfigDeserializer.unsupportedKeyException=Unsupported key: {0}",
"LogicalImagerConfigDeserializer.fullPathsException=A rule with full-paths cannot have other rule definitions",
})
"LogicalImagerConfigDeserializer.fullPathsException=A rule with full-paths cannot have other rule definitions",})
class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerConfig> {
@Override
@ -64,7 +63,7 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
}
List<LogicalImagerRuleSet> ruleSets = new ArrayList<>();
for (JsonElement element: asJsonArray) {
for (JsonElement element : asJsonArray) {
String setName = null;
List<LogicalImagerRule> rules = null;
JsonObject asJsonObject = element.getAsJsonObject();
@ -77,11 +76,11 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
}
return new LogicalImagerConfig(version, finalizeImageWriter, ruleSets);
}
private List<LogicalImagerRule> parseRules(JsonArray asJsonArray) {
List<LogicalImagerRule> rules = new ArrayList<>();
for (JsonElement element: asJsonArray) {
for (JsonElement element : asJsonArray) {
String key1;
Boolean shouldSave = false;
Boolean shouldAlert = true;
@ -91,12 +90,12 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
List<String> paths = null;
List<String> fullPaths = null;
List<String> filenames = null;
Integer minFileSize = null;
Integer maxFileSize = null;
Long minFileSize = null;
Long maxFileSize = null;
Integer minDays = null;
Integer minDate = null;
Integer maxDate = null;
Set<Map.Entry<String, JsonElement>> entrySet = element.getAsJsonObject().entrySet();
for (Map.Entry<String, JsonElement> entry1 : entrySet) {
@ -149,11 +148,11 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
String sizeKey = entry2.getKey();
switch (sizeKey) {
case "min": // NON-NLS
minFileSize = entry2.getValue().getAsInt();
minFileSize = entry2.getValue().getAsLong();
break;
case "max": // NON-NLS
maxFileSize = entry2.getValue().getAsInt();
break;
maxFileSize = entry2.getValue().getAsLong();
break;
default:
throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_unsupportedKeyException(sizeKey));
}
@ -172,7 +171,7 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
maxDate = entry2.getValue().getAsInt();
break;
case "min-days": // NON-NLS
minDays = entry2.getValue().getAsInt();
minDays = entry2.getValue().getAsInt();
break;
default:
throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_unsupportedKeyException(dateKey));
@ -190,7 +189,7 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
|| (filenames != null && !filenames.isEmpty()))) {
throw new JsonParseException(Bundle.LogicalImagerConfigDeserializer_fullPathsException());
}
LogicalImagerRule rule = new LogicalImagerRule.Builder()
.getShouldAlert(shouldAlert)
.getShouldSave(shouldSave)
@ -208,11 +207,7 @@ class LogicalImagerConfigDeserializer implements JsonDeserializer<LogicalImagerC
.build();
rules.add(rule);
} // for
return rules;
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -31,51 +31,51 @@ import java.util.Map;
*/
class LogicalImagerRule {
@Expose(serialize = true)
@Expose(serialize = true)
private final Boolean shouldAlert;
@Expose(serialize = true)
@Expose(serialize = true)
private final Boolean shouldSave;
@Expose(serialize = true)
@Expose(serialize = true)
private final String name;
@Expose(serialize = true)
@Expose(serialize = true)
private final String description;
@Expose(serialize = true)
@Expose(serialize = true)
private List<String> extensions = new ArrayList<>();
@SerializedName("file-names")
@Expose(serialize = true)
@Expose(serialize = true)
private List<String> filenames = new ArrayList<>();
@SerializedName("folder-names")
@Expose(serialize = true)
@Expose(serialize = true)
private List<String> paths = new ArrayList<>();
@SerializedName("full-paths")
@Expose(serialize = true)
@Expose(serialize = true)
private List<String> fullPaths = new ArrayList<>();
@SerializedName("size-range")
@Expose(serialize = true)
final private Map<String, Integer> sizeRange = new HashMap<>();
@SerializedName("date-range")
@Expose(serialize = true)
@SerializedName("size-range")
@Expose(serialize = true)
final private Map<String, Long> sizeRange = new HashMap<>();
@SerializedName("date-range")
@Expose(serialize = true)
final private Map<String, Integer> dateRange = new HashMap<>();
// The following fields should not be serialized, internal use only
@Expose(serialize = false)
private Integer minFileSize;
@Expose(serialize = false)
private Integer maxFileSize;
@Expose(serialize = false)
@Expose(serialize = false)
private Long minFileSize;
@Expose(serialize = false)
private Long maxFileSize;
@Expose(serialize = false)
private Integer minDays;
@Expose(serialize = false)
@Expose(serialize = false)
private Integer minDate;
@Expose(serialize = false)
@Expose(serialize = false)
private Integer maxDate;
private LogicalImagerRule(Boolean shouldAlert, Boolean shouldSave, String name, String description,
List<String> extensions,
List<String> filenames,
List<String> paths,
List<String> fullPaths,
Integer minFileSize,
Integer maxFileSize,
Long minFileSize,
Long maxFileSize,
Integer minDays,
Integer minDate,
Integer maxDate
@ -88,7 +88,7 @@ class LogicalImagerRule {
this.filenames = filenames;
this.paths = paths;
this.fullPaths = fullPaths;
this.sizeRange.put("min", minFileSize); // NON-NLS
this.minFileSize = minFileSize;
this.sizeRange.put("max", maxFileSize); // NON-NLS
@ -107,7 +107,7 @@ class LogicalImagerRule {
this.description = null;
this.name = null;
}
Boolean isShouldAlert() {
return shouldAlert;
}
@ -140,11 +140,11 @@ class LogicalImagerRule {
return fullPaths;
}
Integer getMinFileSize() {
Long getMinFileSize() {
return minFileSize;
}
Integer getMaxFileSize() {
Long getMaxFileSize() {
return maxFileSize;
}
@ -164,87 +164,88 @@ class LogicalImagerRule {
* Builder class
*/
static class Builder {
private Boolean shouldAlert = null;
private Boolean shouldSave = null;
private String name = null;
private String description = null;
private List<String> extensions = null;
private List<String> filenames = null;
private List<String> paths = null;
private List<String> fullPaths = null;
private Integer minFileSize = null;
private Integer maxFileSize = null;
private List<String> filenames = null;
private List<String> paths = null;
private List<String> fullPaths = null;
private Long minFileSize = null;
private Long maxFileSize = null;
private Integer minDays = null;
private Integer minDate = null;
private Integer maxDate = null;
Builder getShouldAlert(boolean shouldAlert) {
this.shouldAlert = shouldAlert;
return this;
}
Builder getShouldSave(boolean shouldSave) {
this.shouldSave = shouldSave;
return this;
}
Builder getName(String name) {
this.name = name;
return this;
}
Builder getDescription(String description) {
this.description = description;
return this;
}
Builder getExtensions(List<String> extensions) {
this.extensions = extensions;
return this;
}
Builder getFilenames(List<String> filenames) {
this.filenames = filenames;
return this;
}
Builder getPaths(List<String> paths) {
this.paths = paths;
return this;
}
Builder getFullPaths(List<String> fullPaths) {
this.fullPaths = fullPaths;
return this;
}
Builder getMinFileSize(Integer minFileSize) {
Builder getMinFileSize(Long minFileSize) {
this.minFileSize = minFileSize;
return this;
}
Builder getMaxFileSize(Integer maxFileSize) {
Builder getMaxFileSize(Long maxFileSize) {
this.maxFileSize = maxFileSize;
return this;
}
Builder getMinDays(Integer minDays) {
this.minDays = minDays;
return this;
}
Builder getMinDate(Integer minDate) {
this.minDate = minDate;
return this;
}
Builder getMaxDate(Integer maxDate) {
this.maxDate = maxDate;
return this;
}
LogicalImagerRule build() {
return new LogicalImagerRule(shouldAlert, shouldSave, name, description,
return new LogicalImagerRule(shouldAlert, shouldSave, name, description,
extensions, filenames, paths, fullPaths,
minFileSize, maxFileSize,
minDays, minDate, maxDate

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -28,11 +28,11 @@ import java.util.List;
class LogicalImagerRuleSet {
@SerializedName("set-name")
@Expose(serialize = true)
@Expose(serialize = true)
final private String setName;
@SerializedName("rules")
@Expose(serialize = true)
@Expose(serialize = true)
private final List<LogicalImagerRule> rules;
LogicalImagerRuleSet(String setName, List<LogicalImagerRule> rules) {
@ -49,8 +49,8 @@ class LogicalImagerRuleSet {
}
/*
* Find a rule with the given name. Return null if not found.
*/
* Find a rule with the given name. Return null if not found.
*/
LogicalImagerRule find(String name) {
for (LogicalImagerRule rule : rules) {
if (rule.getName().equals(name)) {

View File

@ -22,7 +22,9 @@
<Component id="chooseLabel" max="32767" attributes="0"/>
<Component id="chooseComboBox" max="32767" attributes="0"/>
</Group>
<EmptySpace pref="716" max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ruleDescription" min="-2" pref="562" max="-2" attributes="0"/>
<EmptySpace pref="114" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
@ -37,7 +39,10 @@
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="chooseLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="chooseComboBox" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="chooseComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="ruleDescription" alignment="3" min="-2" pref="20" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="sharedLayeredPane" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
@ -49,18 +54,15 @@
<Component class="javax.swing.JLabel" name="chooseLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="NewRuleSetPanel.chooseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<ResourceString bundle="org/sleuthkit/autopsy/logicalimager/configuration/Bundle.properties" key="NewRulePanel.chooseLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="chooseComboBox">
<Properties>
<Property name="maximumRowCount" type="int" value="2"/>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="2">
<StringItem index="0" value="By Attribute"/>
<StringItem index="1" value="By Full Path"/>
</StringArray>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.DefaultComboBoxModel&lt;&gt;(new String[] {Bundle.NewRuleSetPanel_attributeRule_name(), Bundle.NewRuleSetPanel_fullPathRule_name()})" type="code"/>
</Property>
</Properties>
<Events>
@ -80,10 +82,12 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<EmptySpace min="0" pref="373" max="32767" attributes="0"/>
<EmptySpace min="0" pref="467" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
</Container>
<Component class="javax.swing.JLabel" name="ruleDescription">
</Component>
</SubComponents>
</Form>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -20,16 +20,20 @@ package org.sleuthkit.autopsy.logicalimager.configuration;
import java.awt.BorderLayout;
import java.io.IOException;
import java.util.logging.Level;
import javax.swing.JButton;
import javax.swing.JPanel;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* New rule set panel
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
class NewRuleSetPanel extends javax.swing.JPanel {
class NewRulePanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(NewRulePanel.class.getName());
private final JPanel nonFullPathsJPanel;
private final EditNonFullPathsRulePanel editNonFullPathsRulePanel;
private final JPanel fullPathsPanel;
@ -38,13 +42,13 @@ class NewRuleSetPanel extends javax.swing.JPanel {
/**
* Creates new form NewRuleSetPanel
*/
NewRuleSetPanel(JButton okButton, JButton cancelButton) {
NewRulePanel(JButton okButton, JButton cancelButton) {
initComponents();
nonFullPathsJPanel = createPanel();
editNonFullPathsRulePanel = new EditNonFullPathsRulePanel(okButton, cancelButton, "", new LogicalImagerRule(), false);
nonFullPathsJPanel.add(editNonFullPathsRulePanel, BorderLayout.NORTH);
fullPathsPanel = createPanel();
editFullPathsRulePanel = new EditFullPathsRulePanel(okButton, cancelButton, "", new LogicalImagerRule(), false);
fullPathsPanel.add(editFullPathsRulePanel, BorderLayout.NORTH);
@ -52,12 +56,13 @@ class NewRuleSetPanel extends javax.swing.JPanel {
sharedLayeredPane.add(nonFullPathsJPanel, Integer.valueOf(0));
sharedLayeredPane.add(fullPathsPanel, Integer.valueOf(1));
nonFullPathsJPanel.setVisible(true);
ruleDescription.setText(Bundle.NewRuleSetPanel_attributeRule_description());
fullPathsPanel.setVisible(false);
}
private JPanel createPanel() {
JPanel panel = new JPanel(new BorderLayout());
panel.setSize(800, 640);
panel.setSize(800, 650);
return panel;
}
@ -66,6 +71,10 @@ class NewRuleSetPanel extends javax.swing.JPanel {
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@Messages({"NewRuleSetPanel.attributeRule.name=Attribute",
"NewRuleSetPanel.fullPathRule.name=Full Path",
"NewRuleSetPanel.attributeRule.description=Search for files based on one or more attributes or metadata fields.",
"NewRuleSetPanel.fullPathRule.description=Search for files based on full exact match path."})
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
@ -73,11 +82,12 @@ class NewRuleSetPanel extends javax.swing.JPanel {
chooseLabel = new javax.swing.JLabel();
chooseComboBox = new javax.swing.JComboBox<>();
sharedLayeredPane = new javax.swing.JLayeredPane();
ruleDescription = new javax.swing.JLabel();
org.openide.awt.Mnemonics.setLocalizedText(chooseLabel, org.openide.util.NbBundle.getMessage(NewRuleSetPanel.class, "NewRuleSetPanel.chooseLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(chooseLabel, org.openide.util.NbBundle.getMessage(NewRulePanel.class, "NewRulePanel.chooseLabel.text")); // NOI18N
chooseComboBox.setMaximumRowCount(2);
chooseComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "By Attribute", "By Full Path" }));
chooseComboBox.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] {Bundle.NewRuleSetPanel_attributeRule_name(), Bundle.NewRuleSetPanel_fullPathRule_name()}));
chooseComboBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
chooseComboBoxActionPerformed(evt);
@ -92,7 +102,7 @@ class NewRuleSetPanel extends javax.swing.JPanel {
);
sharedLayeredPaneLayout.setVerticalGroup(
sharedLayeredPaneLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 373, Short.MAX_VALUE)
.addGap(0, 467, Short.MAX_VALUE)
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
@ -104,7 +114,9 @@ class NewRuleSetPanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(chooseLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(chooseComboBox, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(716, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ruleDescription, javax.swing.GroupLayout.PREFERRED_SIZE, 562, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(114, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(sharedLayeredPane)
@ -116,7 +128,9 @@ class NewRuleSetPanel extends javax.swing.JPanel {
.addContainerGap()
.addComponent(chooseLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(chooseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(chooseComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(ruleDescription, javax.swing.GroupLayout.PREFERRED_SIZE, 20, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sharedLayeredPane)
.addContainerGap())
@ -125,18 +139,29 @@ class NewRuleSetPanel extends javax.swing.JPanel {
private void chooseComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseComboBoxActionPerformed
int index = chooseComboBox.getSelectedIndex();
if (index == 0) {
if (chooseComboBox.getItemAt(index).equals(Bundle.NewRuleSetPanel_attributeRule_name())) {
nonFullPathsJPanel.setVisible(true);
editNonFullPathsRulePanel.setOkButton();
ruleDescription.setText(Bundle.NewRuleSetPanel_attributeRule_description());
fullPathsPanel.setVisible(false);
} else {
nonFullPathsJPanel.setVisible(false);
} else if (chooseComboBox.getItemAt(index).equals(Bundle.NewRuleSetPanel_fullPathRule_name())) {
nonFullPathsJPanel.setVisible(false);
ruleDescription.setText(Bundle.NewRuleSetPanel_fullPathRule_description());
fullPathsPanel.setVisible(true);
editFullPathsRulePanel.setOkButton();
} else {
logger.log(Level.WARNING, "Rule type selected was not one of the expected rule types");
nonFullPathsJPanel.setVisible(false);
fullPathsPanel.setVisible(false);
ruleDescription.setText("");
}
}//GEN-LAST:event_chooseComboBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JComboBox<String> chooseComboBox;
private javax.swing.JLabel chooseLabel;
private javax.swing.JLabel ruleDescription;
private javax.swing.JLayeredPane sharedLayeredPane;
// End of variables declaration//GEN-END:variables
@ -146,7 +171,7 @@ class NewRuleSetPanel extends javax.swing.JPanel {
ruleMap = editNonFullPathsRulePanel.toRule();
} else {
ruleMap = editFullPathsRulePanel.toRule();
}
}
return ruleMap;
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2013-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -36,26 +36,25 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A runnable that
* - copy the logical image folder to a destination folder
* - add alert.txt and users.txt files to report
* - add an image data source to the case database.
* A runnable that - copy the logical image folder to a destination folder - add
* alert.txt and users.txt files to report - add an image data source to the
* case database.
*/
final class AddLogicalImageTask extends AddMultipleImageTask {
private final static Logger logger = Logger.getLogger(AddLogicalImageTask.class.getName());
private final static Logger logger = Logger.getLogger(AddLogicalImageTask.class.getName());
private final static String ALERT_TXT = "alert.txt"; //NON-NLS
private final static String USERS_TXT = "users.txt"; //NON-NLS
private final File src;
private final File dest;
private final DataSourceProcessorCallback callback;
private final DataSourceProcessorProgressMonitor progressMonitor;
AddLogicalImageTask(String deviceId,
List<String> imagePaths,
String timeZone,
AddLogicalImageTask(String deviceId,
List<String> imagePaths,
String timeZone,
File src, File dest,
DataSourceProcessorProgressMonitor progressMonitor,
DataSourceProcessorProgressMonitor progressMonitor,
DataSourceProcessorCallback callback
) throws NoCurrentCaseException {
super(deviceId, imagePaths, timeZone, progressMonitor, callback);
@ -64,11 +63,10 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
this.progressMonitor = progressMonitor;
this.callback = callback;
}
/**
* Copy the src directory to dest.
* Add alert.txt and users.txt to the case report
* Adds the image to the case database.
* Copy the src directory to dest. Add alert.txt and users.txt to the case
* report Adds the image to the case database.
*/
@Messages({
"# {0} - src", "# {1} - dest", "AddLogicalImageTask.copyingImageFromTo=Copying image from {0} to {1}",
@ -81,7 +79,7 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
public void run() {
List<String> errorList = new ArrayList<>();
List<Content> emptyDataSources = new ArrayList<>();
try {
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_copyingImageFromTo(src.toString(), dest.toString()));
FileUtils.copyDirectory(src, dest);
@ -94,7 +92,7 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
// Add the alert.txt and users.txt to the case report
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_addingToReport(ALERT_TXT));
String status = addReport(Paths.get(dest.toString(), ALERT_TXT), ALERT_TXT + " " + src.getName());
@ -113,15 +111,16 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
return;
}
progressMonitor.setProgressText(Bundle.AddLogicalImageTask_doneAddingToReport(USERS_TXT));
super.run();
}
/**
/**
* Add a file specified by the reportPath to the case report.
*
*
* @param reportPath Path to the report to be added
* @param reportName Name associated the report
*
* @returns null if success, or exception message if failure
*
*/
@ -139,6 +138,6 @@ final class AddLogicalImageTask extends AddMultipleImageTask {
String msg = Bundle.AddLogicalImageTask_failedToAddReport(reportPath.toString(), ex.getMessage());
logger.log(Level.SEVERE, String.format("Failed to add report {0}. Reason= {1}", reportPath.toString(), ex.getMessage()));
return msg;
}
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2013-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -40,9 +40,9 @@ import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException;
/**
*
*
* A runnable that adds multiple images to the case database
*
*
*/
@Messages({
"AddMultipleImageTask.fsTypeUnknownErr=Cannot determine file system type"
@ -59,12 +59,11 @@ class AddMultipleImageTask implements Runnable {
private final Case currentCase;
private boolean criticalErrorOccurred;
private volatile boolean cancelled;
/**
* Constructs a runnable that adds multiple image files
* to a case database. If Sleuth Kit fails to find a filesystem
* in any of input image files, the file is added to the case as a
* local/logical file instead.
* Constructs a runnable that adds multiple image files to a case database.
* If Sleuth Kit fails to find a filesystem in any of input image files, the
* file is added to the case as a local/logical file instead.
*
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is intended
@ -76,14 +75,14 @@ class AddMultipleImageTask implements Runnable {
* @param progressMonitor Progress monitor for reporting progress during
* processing.
* @param callback Callback to call when processing is done.
* @throws NoCurrentCaseException The exception if there is no open case.
*
* @throws NoCurrentCaseException The exception if there is no open case.
*/
@Messages({
"# {0} - file", "AddMultipleImageTask.addingFileAsLogicalFile=Adding: {0} as logical file",
"# {0} - deviceId", "# {1} - exceptionMessage",
"AddMultipleImageTask.errorAddingImgWithoutFileSystem=Error adding images without file systems for device %s: %s",
})
AddMultipleImageTask(String deviceId, List<String> imageFilePaths, String timeZone,
"# {0} - deviceId", "# {1} - exceptionMessage",
"AddMultipleImageTask.errorAddingImgWithoutFileSystem=Error adding images without file systems for device %s: %s",})
AddMultipleImageTask(String deviceId, List<String> imageFilePaths, String timeZone,
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) throws NoCurrentCaseException {
this.deviceId = deviceId;
this.imageFilePaths = imageFilePaths;
@ -171,9 +170,9 @@ class AddMultipleImageTask implements Runnable {
* added to this list for eventual return to
* the caller via the callback.
* @param localFileDataSourcePaths If the image cannot be added because
* Sleuth Kit cannot detect a filesystem, the
* image file path is added to this list for
* later addition as a part of a
* Sleuth Kit cannot detect a filesystem,
* the image file path is added to this list
* for later addition as a part of a
* local/logical files data source.
* @param errorMessages If there are any error messages, the
* error messages are added to this list for
@ -184,8 +183,7 @@ class AddMultipleImageTask implements Runnable {
"# {0} - imageFilePath", "AddMultipleImageTask.adding=Adding: {0}",
"# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.criticalErrorAdding=Critical error adding {0} for device {1}: {2}",
"# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.criticalErrorReverting=Critical error reverting add image process for {0} for device {1}: {2}",
"# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.nonCriticalErrorAdding=Non-critical error adding {0} for device {1}: {2}",
})
"# {0} - imageFilePath", "# {1} - deviceId", "# {2} - exceptionMessage", "AddMultipleImageTask.nonCriticalErrorAdding=Non-critical error adding {0} for device {1}: {2}",})
private void addImageToCase(String imageFilePath, List<Content> newDataSources, List<String> localFileDataSourcePaths, List<String> errorMessages) {
/*
* Try to add the image to the case database as a data source.
@ -251,4 +249,4 @@ class AddMultipleImageTask implements Runnable {
}
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Autopsy
*
* 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.logicalimager.dsp;
/**
* Utility class for displaying a list of drives
*/
public final class DriveListUtils {
/**
* Convert a number of bytes to a human readable string
*
* @param bytes the number of bytes to convert
* @param si whether it takes 1000 or 1024 of a unit to reach the next
* unit
*
* @return a human readable string representing the number of bytes
*/
public static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) {
return bytes + " B"; //NON-NLS
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); //NON-NLS
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); //NON-NLS
}
/**
* Empty private constructor for util class
*/
private DriveListUtils() {
//empty private constructor for util class
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,20 +38,20 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
import org.sleuthkit.datamodel.Content;
/**
* A Logical Imager data source processor that implements the DataSourceProcessor service
* provider interface to allow integration with the add data source wizard. It
* also provides a run method overload to allow it to be used independently of
* the wizard.
* A Logical Imager data source processor that implements the
* DataSourceProcessor service provider interface to allow integration with the
* add data source wizard. It also provides a run method overload to allow it to
* be used independently of the wizard.
*/
@ServiceProviders(value={
@ServiceProvider(service=DataSourceProcessor.class)}
@ServiceProviders(value = {
@ServiceProvider(service = DataSourceProcessor.class)}
)
public final class LogicalImagerDSProcessor implements DataSourceProcessor {
private static final String LOGICAL_IMAGER_DIR = "LogicalImager"; //NON-NLS
private final LogicalImagerPanel configPanel;
private AddLogicalImageTask addLogicalImageTask;
/*
* Constructs a Logical Imager data source processor that implements the
* DataSourceProcessor service provider interface to allow integration with
@ -131,16 +131,15 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
"# {0} - directory", "LogicalImagerDSProcessor.failToCreateDirectory=Failed to create directory {0}",
"# {0} - directory", "LogicalImagerDSProcessor.directoryAlreadyExists=Directory {0} already exists",
"# {0} - file", "LogicalImagerDSProcessor.failToGetCanonicalPath=Fail to get canonical path for {0}",
"LogicalImagerDSProcessor.noCurrentCase=No current case",
})
"LogicalImagerDSProcessor.noCurrentCase=No current case",})
@Override
public void run(DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
configPanel.storeSettings();
Path imageDirPath = configPanel.getImageDirPath();
List<String> errorList = new ArrayList<>();
List<Content> emptyDataSources = new ArrayList<>();
if (!imageDirPath.toFile().exists()) {
// This can happen if the USB drive was selected in the panel, but
// was ejected before pressing the NEXT button
@ -150,7 +149,7 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
callback.done(DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS, errorList, emptyDataSources);
return;
}
// Create the LogicalImager directory under ModuleDirectory
String moduleDirectory = Case.getCurrentCase().getModuleDirectory();
File logicalImagerDir = Paths.get(moduleDirectory, LOGICAL_IMAGER_DIR).toFile();
@ -170,7 +169,7 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
return;
}
File src = imageDirPath.toFile();
// Get all VHD files in the src directory
List<String> imagePaths = new ArrayList<>();
for (File f : src.listFiles()) {
@ -189,8 +188,8 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
String deviceId = UUID.randomUUID().toString();
String timeZone = Calendar.getInstance().getTimeZone().getID();
run(deviceId, imagePaths,
timeZone, src, dest,
progressMonitor, callback);
timeZone, src, dest,
progressMonitor, callback);
} catch (NoCurrentCaseException ex) {
String msg = Bundle.LogicalImagerDSProcessor_noCurrentCase();
errorList.add(msg);
@ -198,29 +197,28 @@ public final class LogicalImagerDSProcessor implements DataSourceProcessor {
return;
}
}
/**
* Adds a "Logical Imager" data source to the case database using a background task in
* a separate thread and the given settings instead of those provided by the
* selection and configuration panel. Returns as soon as the background task
* is started and uses the callback object to signal task completion and
* return results.
* Adds a "Logical Imager" data source to the case database using a
* background task in a separate thread and the given settings instead of
* those provided by the selection and configuration panel. Returns as soon
* as the background task is started and uses the callback object to signal
* task completion and return results.
*
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is
* intended to be unique across multiple cases
* (e.g., a UUID).
* @param imagePaths Paths to the image files.
* @param timeZone The time zone to use when processing dates
* and times for the image, obtained from
* java.util.TimeZone.getID.
* @param src The source directory of image.
* @param dest The destination directory to copy the source.
* @param progressMonitor Progress monitor for reporting progress
* during processing.
* @param callback Callback to call when processing is done.
* @param deviceId An ASCII-printable identifier for the device
* associated with the data source that is intended
* to be unique across multiple cases (e.g., a UUID).
* @param imagePaths Paths to the image files.
* @param timeZone The time zone to use when processing dates and
* times for the image, obtained from
* java.util.TimeZone.getID.
* @param src The source directory of image.
* @param dest The destination directory to copy the source.
* @param progressMonitor Progress monitor for reporting progress during
* processing.
* @param callback Callback to call when processing is done.
*/
private void run(String deviceId, List<String> imagePaths, String timeZone,
private void run(String deviceId, List<String> imagePaths, String timeZone,
File src, File dest,
DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback
) throws NoCurrentCaseException {

View File

@ -72,7 +72,7 @@
<Component id="jScrollPane1" min="-2" pref="568" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace pref="338" max="32767" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -89,7 +89,7 @@
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="imageScrollPane" pref="0" max="32767" attributes="0"/>
<Component id="driveListScrollPane" pref="461" max="32767" attributes="0"/>
<Component id="driveListScrollPane" pref="106" max="32767" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="refreshButton" min="-2" max="-2" attributes="0"/>

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
* Autopsy
*
* Copyright 2011-2019 Basis Technology Corp.
* Copyright 2019 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -29,6 +29,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JFileChooser;
@ -42,6 +43,7 @@ import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Panel for adding an logical image file from drive letters. Allows the user to
@ -54,6 +56,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
final class LogicalImagerPanel extends JPanel implements DocumentListener {
private static final Logger logger = Logger.getLogger(LogicalImagerPanel.class.getName());
private static final long serialVersionUID = 1L;
private static final String NO_IMAGE_SELECTED = Bundle.LogicalImagerPanel_messageLabel_noImageSelected();
private static final String DRIVE_HAS_NO_IMAGES = Bundle.LogicalImagerPanel_messageLabel_driveHasNoImages();
@ -255,7 +258,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 568, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(338, Short.MAX_VALUE))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -269,7 +272,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(imageScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE)
.addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 461, Short.MAX_VALUE))
.addComponent(driveListScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 106, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(refreshButton)
.addGap(18, 18, 18)
@ -288,16 +291,6 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
);
}// </editor-fold>//GEN-END:initComponents
private static String humanReadableByteCount(long bytes, boolean si) {
int unit = si ? 1000 : 1024;
if (bytes < unit) {
return bytes + " B"; //NON-NLS
}
int exp = (int) (Math.log(bytes) / Math.log(unit));
String pre = (si ? "kMGTPE" : "KMGTPE").charAt(exp - 1) + (si ? "" : "i"); //NON-NLS
return String.format("%.1f %sB", bytes / Math.pow(unit, exp), pre); //NON-NLS
}
@Messages({
"# {0} - sparseImageDirectory",
"LogicalImagerPanel.messageLabel.directoryDoesNotContainSparseImage=Directory {0} does not contain any images",
@ -490,7 +483,7 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
for (File root : roots) {
String description = FileSystemView.getFileSystemView().getSystemTypeDescription(root);
long spaceInBytes = root.getTotalSpace();
String sizeWithUnit = humanReadableByteCount(spaceInBytes, false);
String sizeWithUnit = DriveListUtils.humanReadableByteCount(spaceInBytes, false);
listData.add(root + " (" + description + ") (" + sizeWithUnit + ")");
if (firstRemovableDrive == -1) {
try {
@ -498,9 +491,9 @@ final class LogicalImagerPanel extends JPanel implements DocumentListener {
if ((boolean) fileStore.getAttribute("volume:isRemovable")) { //NON-NLS
firstRemovableDrive = i;
}
} catch (IOException ex) {
i++;
continue;
} catch (IOException ignored) {
//unable to get this removable drive for default selection will try and select next removable drive by default
logger.log(Level.INFO, "Unable to select first removable drive found", ignored);
}
}
i++;

View File

@ -27,7 +27,7 @@
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,-116,0,0,2,-108"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout"/>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
@ -36,13 +36,16 @@
<EtchetBorder/>
</Border>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[182, 24]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 81]"/>
<Dimension value="[182, 24]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.0" weightY="0.0"/>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="North"/>
</Constraint>
</Constraints>
@ -65,7 +68,7 @@
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="3" gridY="1" gridWidth="1" gridHeight="3" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.1" weightY="0.0"/>
<GridBagConstraints gridX="3" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.1" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@ -84,7 +87,7 @@
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="5" gridY="1" gridWidth="2" gridHeight="3" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.1" weightY="0.0"/>
<GridBagConstraints gridX="5" gridY="0" gridWidth="2" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="5" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.1" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@ -97,7 +100,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="4" gridY="1" gridWidth="1" gridHeight="3" fill="3" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="4" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="13" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@ -109,7 +112,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="3" fill="1" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.25" weightY="0.0"/>
<GridBagConstraints gridX="0" gridY="0" gridWidth="1" gridHeight="1" fill="2" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="17" weightX="0.25" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@ -121,7 +124,7 @@
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="2" gridY="1" gridWidth="1" gridHeight="3" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
<GridBagConstraints gridX="2" gridY="0" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="10" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
@ -131,19 +134,19 @@
<Properties>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[2000, 2000]"/>
<Dimension value="[20000, 20000]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[660, 344]"/>
<Dimension value="[640, 250]"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="1" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="6" insetsLeft="0" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout" value="org.netbeans.modules.form.compat2.layouts.DesignBorderLayout$BorderConstraintsDescription">
<BorderConstraints direction="Center"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
</Container>
</SubComponents>
</Form>
</Form>

View File

@ -299,18 +299,18 @@ public class TranslationContentPanel extends javax.swing.JPanel {
setName(""); // NOI18N
setPreferredSize(new java.awt.Dimension(100, 58));
setVerifyInputWhenFocusTarget(false);
setLayout(new java.awt.GridBagLayout());
setLayout(new java.awt.BorderLayout());
jPanel1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
jPanel1.setPreferredSize(new java.awt.Dimension(250, 81));
jPanel1.setMaximumSize(new java.awt.Dimension(182, 24));
jPanel1.setPreferredSize(new java.awt.Dimension(182, 24));
jPanel1.setLayout(new java.awt.GridBagLayout());
displayTextComboBox.setMinimumSize(new java.awt.Dimension(43, 20));
displayTextComboBox.setPreferredSize(new java.awt.Dimension(43, 20));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 3;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridheight = 3;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.weightx = 0.1;
@ -322,9 +322,8 @@ public class TranslationContentPanel extends javax.swing.JPanel {
ocrDropdown.setName(""); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 5;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.gridheight = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.weightx = 0.1;
@ -335,9 +334,7 @@ public class TranslationContentPanel extends javax.swing.JPanel {
ocrLabel.setEnabled(false);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 4;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridheight = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.VERTICAL;
gridBagConstraints.gridy = 0;
gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
gridBagConstraints.insets = new java.awt.Insets(0, 10, 0, 0);
jPanel1.add(ocrLabel, gridBagConstraints);
@ -345,9 +342,8 @@ public class TranslationContentPanel extends javax.swing.JPanel {
warningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/images/warning16.png"))); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridheight = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.weightx = 0.25;
jPanel1.add(warningLabel, gridBagConstraints);
@ -355,29 +351,15 @@ public class TranslationContentPanel extends javax.swing.JPanel {
org.openide.awt.Mnemonics.setLocalizedText(showLabel, org.openide.util.NbBundle.getMessage(TranslationContentPanel.class, "TranslationContentPanel.showLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridheight = 3;
gridBagConstraints.gridy = 0;
jPanel1.add(showLabel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(jPanel1, gridBagConstraints);
add(jPanel1, java.awt.BorderLayout.NORTH);
textScrollPane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
textScrollPane.setMaximumSize(new java.awt.Dimension(2000, 2000));
textScrollPane.setPreferredSize(new java.awt.Dimension(660, 344));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(6, 0, 0, 0);
add(textScrollPane, gridBagConstraints);
textScrollPane.setMaximumSize(new java.awt.Dimension(20000, 20000));
textScrollPane.setPreferredSize(new java.awt.Dimension(640, 250));
add(textScrollPane, java.awt.BorderLayout.CENTER);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
@ -389,4 +371,4 @@ public class TranslationContentPanel extends javax.swing.JPanel {
private javax.swing.JScrollPane textScrollPane;
private javax.swing.JLabel warningLabel;
// End of variables declaration//GEN-END:variables
}
}

View File

@ -25,7 +25,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="nodeScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="nodeScrollPane" alignment="0" pref="656" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -49,8 +49,8 @@
<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"/>
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Component id="jLabelSelectInputFolder" min="-2" max="-2" attributes="0"/>
@ -117,8 +117,11 @@
</Group>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<Component id="autoIngestModeRadioButton" min="-2" pref="145" max="-2" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="autoIngestModeRadioButton" min="-2" pref="145" max="-2" attributes="0"/>
<Component id="pnTestMultiUser" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
@ -187,7 +190,9 @@
</Group>
<EmptySpace max="-2" attributes="0"/>
<Component id="pbTaskInProgress" min="-2" pref="22" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="pnTestMultiUser" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="82" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -460,6 +465,100 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="autoIngestModeRadioButtonActionPerformed"/>
</Events>
</Component>
<Container class="javax.swing.JPanel" name="pnTestMultiUser">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
<EtchetBorder/>
</Border>
</Property>
</Properties>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lbTestResultText" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="lbTestMultiUserText" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="236" max="32767" attributes="0"/>
<Component id="bnTestMultiUser" min="-2" pref="83" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="lbMultiUserResult" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="8" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" 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="1" attributes="0">
<Component id="lbMultiUserResult" alignment="1" min="-2" pref="23" max="-2" attributes="0"/>
<Group type="103" alignment="1" groupAlignment="3" attributes="0">
<Component id="bnTestMultiUser" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lbTestMultiUserText" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="lbTestResultText" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace min="0" pref="16" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JLabel" name="lbTestMultiUserText">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="lbTestMultiUserText" property="font" relativeSize="false" size="12"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.lbTestMultiUserText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="bnTestMultiUser">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="bnTestMultiUser" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.bnTestMultiUser.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnTestMultiUserActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="lbMultiUserResult">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.lbMultiUserResult.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lbTestResultText">
<Properties>
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
<Color blue="0" green="0" red="ff" type="rgb"/>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/experimental/configuration/Bundle.properties" key="AutoIngestSettingsPanel.lbTestResultText.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Container>
</SubComponents>

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.experimental.configuration;
import java.awt.BorderLayout;
import java.awt.Cursor;
import java.awt.Color;
import java.io.File;
import java.nio.file.Files;
import java.util.List;
@ -35,6 +36,7 @@ import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobSettingsPanel;
import java.awt.Dimension;
import java.nio.file.Paths;
import javax.swing.ImageIcon;
import org.openide.util.ImageUtilities;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
@ -47,8 +49,6 @@ import org.sleuthkit.autopsy.experimental.autoingest.FileExporterSettingsPanel;
/**
* Configuration panel for auto ingest settings.
*/
@Messages({"AutoIngestSettingsPanel.examinerModeRadioButton.text=Examiner mode",
"AutoIngestSettingsPanel.autoIngestModeRadioButton.text=Auto Ingest mode"})
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public class AutoIngestSettingsPanel extends javax.swing.JPanel {
@ -58,7 +58,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(AutoIngestSettingsPanel.class.getName());
private final Integer oldIngestThreads;
private static final String MULTI_USER_SETTINGS_MUST_BE_ENABLED = NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.validationErrMsg.MUdisabled");
private final ImageIcon goodIcon;
private final ImageIcon badIcon;
enum OptionsUiMode {
STANDALONE, AIM, DOWNLOADING_CONFIGURATION
@ -92,6 +94,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
jLabelTaskDescription.setEnabled(false);
this.oldIngestThreads = UserPreferences.numberOfFileIngestThreads();
goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/good.png", false));
badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/experimental/images/bad.png", false));
}
private class MyDocumentListener implements DocumentListener {
@ -121,6 +126,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
* @param inStartup True if we're doing the initial population of the UI
*/
final void load(boolean inStartup) {
lbMultiUserResult.setIcon(null);
lbTestResultText.setText("");
// multi user mode must be enabled
if (!UserPreferences.getIsMultiUserModeEnabled()) {
@ -448,7 +456,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
jLabelInvalidImageFolder.setVisible(true);
jLabelInvalidImageFolder.setText(NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CannotAccess")
+ " " + inputPath + " "
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CheckPermissions"));
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CheckPermissions", System.getProperty("user.name")));
return false;
}
@ -479,7 +487,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
jLabelInvalidResultsFolder.setVisible(true);
jLabelInvalidResultsFolder.setText(NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CannotAccess")
+ " " + outputPath + " "
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CheckPermissions"));
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CheckPermissions", System.getProperty("user.name")));
return false;
}
@ -514,7 +522,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
sharedSettingsErrorTextField.setVisible(true);
sharedSettingsErrorTextField.setText(NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CannotAccess")
+ " " + sharedSettingsPath + " "
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CheckPermissions"));
+ NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.CheckPermissions", System.getProperty("user.name")));
return false;
}
@ -572,6 +580,11 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
downloadButton.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
browseSharedSettingsButton.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected());
uploadButton.setEnabled(mode == OptionsUiMode.AIM && sharedConfigCheckbox.isSelected() && masterNodeCheckBox.isSelected());
lbTestMultiUserText.setEnabled(mode == OptionsUiMode.AIM);
bnTestMultiUser.setEnabled(mode == OptionsUiMode.AIM);
lbMultiUserResult.setEnabled(mode == OptionsUiMode.AIM);
lbTestResultText.setEnabled(mode == OptionsUiMode.AIM);
} else {
setEnabledState(false);
}
@ -623,6 +636,11 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
masterNodeCheckBox = new javax.swing.JCheckBox();
examinerModeRadioButton = new javax.swing.JRadioButton();
autoIngestModeRadioButton = new javax.swing.JRadioButton();
pnTestMultiUser = new javax.swing.JPanel();
lbTestMultiUserText = new javax.swing.JLabel();
bnTestMultiUser = new javax.swing.JButton();
lbMultiUserResult = new javax.swing.JLabel();
lbTestResultText = new javax.swing.JLabel();
nodeScrollPane.setMinimumSize(new java.awt.Dimension(0, 0));
@ -761,6 +779,55 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
}
});
pnTestMultiUser.setBorder(javax.swing.BorderFactory.createEtchedBorder());
lbTestMultiUserText.setFont(lbTestMultiUserText.getFont().deriveFont(lbTestMultiUserText.getFont().getStyle() & ~java.awt.Font.BOLD, 12));
org.openide.awt.Mnemonics.setLocalizedText(lbTestMultiUserText, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.lbTestMultiUserText.text")); // NOI18N
bnTestMultiUser.setFont(bnTestMultiUser.getFont().deriveFont(bnTestMultiUser.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(bnTestMultiUser, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.bnTestMultiUser.text")); // NOI18N
bnTestMultiUser.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bnTestMultiUserActionPerformed(evt);
}
});
org.openide.awt.Mnemonics.setLocalizedText(lbMultiUserResult, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.lbMultiUserResult.text")); // NOI18N
lbTestResultText.setForeground(new java.awt.Color(255, 0, 0));
org.openide.awt.Mnemonics.setLocalizedText(lbTestResultText, org.openide.util.NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.lbTestResultText.text")); // NOI18N
javax.swing.GroupLayout pnTestMultiUserLayout = new javax.swing.GroupLayout(pnTestMultiUser);
pnTestMultiUser.setLayout(pnTestMultiUserLayout);
pnTestMultiUserLayout.setHorizontalGroup(
pnTestMultiUserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnTestMultiUserLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnTestMultiUserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbTestResultText, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(pnTestMultiUserLayout.createSequentialGroup()
.addComponent(lbTestMultiUserText)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 236, Short.MAX_VALUE)
.addComponent(bnTestMultiUser, javax.swing.GroupLayout.PREFERRED_SIZE, 83, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(lbMultiUserResult, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(8, 8, 8)))
.addContainerGap())
);
pnTestMultiUserLayout.setVerticalGroup(
pnTestMultiUserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(pnTestMultiUserLayout.createSequentialGroup()
.addContainerGap()
.addGroup(pnTestMultiUserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbMultiUserResult, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(pnTestMultiUserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(bnTestMultiUser)
.addComponent(lbTestMultiUserText)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(lbTestResultText, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 16, Short.MAX_VALUE))
);
javax.swing.GroupLayout nodePanelLayout = new javax.swing.GroupLayout(nodePanel);
nodePanel.setLayout(nodePanelLayout);
nodePanelLayout.setHorizontalGroup(
@ -820,7 +887,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addGap(0, 0, Short.MAX_VALUE)))
.addGap(10, 10, 10))
.addGroup(nodePanelLayout.createSequentialGroup()
.addComponent(autoIngestModeRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(nodePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(autoIngestModeRadioButton, javax.swing.GroupLayout.PREFERRED_SIZE, 145, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(pnTestMultiUser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, Short.MAX_VALUE))))
);
nodePanelLayout.setVerticalGroup(
@ -875,7 +944,9 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
.addComponent(jLabelTaskDescription))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pbTaskInProgress, javax.swing.GroupLayout.PREFERRED_SIZE, 22, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(pnTestMultiUser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(82, Short.MAX_VALUE))
);
nodeScrollPane.setViewportView(nodePanel);
@ -888,7 +959,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(nodeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(nodeScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 656, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
@ -1075,6 +1146,37 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
controller.changed();
}//GEN-LAST:event_examinerModeRadioButtonActionPerformed
private void bnTestMultiUserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestMultiUserActionPerformed
lbTestResultText.setForeground(Color.BLACK);
lbTestResultText.setText(NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.TestRunning"));
lbTestResultText.paintImmediately(lbTestResultText.getVisibleRect());
lbMultiUserResult.setIcon(null);
lbMultiUserResult.paintImmediately(lbMultiUserResult.getVisibleRect());
if (!validateResultsPath()) {
lbMultiUserResult.setIcon(badIcon);
lbTestResultText.setForeground(Color.RED);
lbTestResultText.setText(NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.PathInvalid"));
return;
}
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
String resultsFolderPath = getNormalizedFolderPath(outputPathTextField.getText().trim());
String testResult = MultiUserTestTool.runTest(resultsFolderPath);
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
if (testResult.equals(MultiUserTestTool.MULTI_USER_TEST_SUCCESSFUL)) {
// test successful
lbMultiUserResult.setIcon(goodIcon);
lbTestResultText.setText("");
} else {
// test failed
lbMultiUserResult.setIcon(badIcon);
lbTestResultText.setText(testResult);
lbTestResultText.setForeground(Color.RED);
}
}//GEN-LAST:event_bnTestMultiUserActionPerformed
private void enableUI(boolean state) {
enableOptionsBasedOnMode(OptionsUiMode.DOWNLOADING_CONFIGURATION);
downloadButton.setEnabled(state);
@ -1198,6 +1300,7 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private javax.swing.JButton bnAdvancedSettings;
private javax.swing.JButton bnEditIngestSettings;
private javax.swing.JButton bnFileExport;
private javax.swing.JButton bnTestMultiUser;
private javax.swing.JButton browseInputFolderButton;
private javax.swing.JButton browseOutputFolderButton;
private javax.swing.JButton browseSharedSettingsButton;
@ -1211,12 +1314,16 @@ public class AutoIngestSettingsPanel extends javax.swing.JPanel {
private javax.swing.JLabel jLabelSelectInputFolder;
private javax.swing.JLabel jLabelSelectOutputFolder;
private javax.swing.JLabel jLabelTaskDescription;
private javax.swing.JLabel lbMultiUserResult;
private javax.swing.JLabel lbTestMultiUserText;
private javax.swing.JLabel lbTestResultText;
private javax.swing.JCheckBox masterNodeCheckBox;
private javax.swing.ButtonGroup modeSelectionButtonGroup;
private javax.swing.JPanel nodePanel;
private javax.swing.JScrollPane nodeScrollPane;
private javax.swing.JTextField outputPathTextField;
private javax.swing.JProgressBar pbTaskInProgress;
private javax.swing.JPanel pnTestMultiUser;
private javax.swing.JCheckBox sharedConfigCheckbox;
private javax.swing.JTextField sharedSettingsErrorTextField;
private javax.swing.JTextField sharedSettingsTextField;

View File

@ -19,10 +19,7 @@
package org.sleuthkit.autopsy.experimental.configuration;
import org.sleuthkit.autopsy.core.UserPreferences;
import org.sleuthkit.autopsy.core.UserPreferencesException;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.TextConverter;
import org.sleuthkit.autopsy.coreutils.TextConverterException;
/**
* Provides convenient access to a Preferences node for auto ingest user
@ -42,12 +39,6 @@ public final class AutoIngestUserPreferences {
private static final String MAX_NUM_TIMES_TO_PROCESS_IMAGE = "MaxNumTimesToAttemptToProcessImage"; // NON-NLS
private static final int DEFAULT_MAX_TIMES_TO_PROCESS_IMAGE = 0;
private static final String MAX_CONCURRENT_NODES_FOR_ONE_CASE = "MaxConcurrentNodesForOneCase"; // NON-NLS
private static final String STATUS_DATABASE_LOGGING_ENABLED = "StatusDatabaseLoggingEnabled"; // NON-NLS
private static final String LOGGING_DB_HOSTNAME_OR_IP = "LoggingHostnameOrIP"; // NON-NLS
private static final String LOGGING_PORT = "LoggingPort"; // NON-NLS
private static final String LOGGING_USERNAME = "LoggingUsername"; // NON-NLS
private static final String LOGGING_PASSWORD = "LoggingPassword"; // NON-NLS
private static final String LOGGING_DATABASE_NAME = "LoggingDatabaseName"; // NON-NLS
private static final String INPUT_SCAN_INTERVAL_TIME = "IntervalBetweenInputScan"; // NON-NLS
// Prevent instantiation.

View File

@ -21,10 +21,11 @@ AIMIngestSettingsPanel.jLabel1.text=Download the current shared setting (highly
AIMIngestSettingsPanel.lbSecondsBetweenJobs.text=Number of seconds to wait between jobs:
AIMIngestSettingsPanel.lbSecondsBetweenJobs.toolTipText=Increase this value if database locks cause problems. It gives a little more time for finalizing.
AIMIngestSettingsPanel.spSecondsBetweenJobs.toolTipText=Increase this value if database locks cause problems. It gives a little more time for finalizing.
AutoIngestSettingsPanel.examinerModeRadioButton.text=Examiner mode
AutoIngestSettingsPanel.autoIngestModeRadioButton.text=Auto Ingest mode
AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title=Advanced Settings
AutoIngestSettingsPanel.browseGlobalSettingsButton.text=Browse
AutoIngestSettingsPanel.CannotAccess=Cannot access
AutoIngestSettingsPanel.CheckPermissions=Check permissions.
AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory
AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder
AutoIngestSettingsPanel.FileExportRules.text=File Export Rules
@ -37,7 +38,6 @@ AutoIngestSettingsPanel.KeywordSearchNull=Cannot find Keyword Search service
AutoIngestSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect
AutoIngestSettingsPanel.nodePanel.TabConstraints.tabTitle=Node Configuration
AutoIngestSettingsPanel.NodeStatusLogging.text=Node Status Logging Settings
AutoIngestSettingsPanel.PathInvalid=Path is not valid
AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required to take effect.
AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required
AutoIngestSettingsPanel.ResultsDirectoryUnspecified=Shared cases folder must be set
@ -47,6 +47,16 @@ AutoIngestSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database po
AutoIngestSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number
AutoIngestSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number
AutoIngestSettingsPanel.validationErrMsg.MUdisabled=Multi user settings must be enabled and saved
AutoIngestSettingsPanel.bnTestMultiUser.text=Test
AutoIngestSettingsPanel.lbTestMultiUserText.text=Test Multi-User Case Creation and Ingest Settings
AutoIngestSettingsPanel.lbMultiUserResult.text=
AutoIngestSettingsPanel.lbTestResultText.text=
AutoIngestSettingsPanel.validationErrMsg.outputPathNotSpecified=Output folder must be set
AutoIngestSettingsPanel.PathInvalid=Case output directory path is not valid
AutoIngestSettingsPanel.CheckPermissions=Ensure that the user account {0} has write permissions in this folder
AutoIngestSettingsPanel.Success=Success
AutoIngestSettingsPanel.TestRunning=Test in progress...
AutoIngestSettingsPanel.servicesDown=Some of the Multi User services are down
GeneralOptionsPanelController.moduleErr.msg=A module caused an error listening to GeneralOptionsPanelController updates. See log to determine which module. Some data could be incomplete.
GeneralOptionsPanelController.moduleErr=Module Error
NodeStatusLogPanel.bnCancel.text=Cancel

View File

@ -21,14 +21,13 @@ AIMIngestSettingsPanel.jLabel1.text=Download the current shared setting (highly
AIMIngestSettingsPanel.lbSecondsBetweenJobs.text=Number of seconds to wait between jobs:
AIMIngestSettingsPanel.lbSecondsBetweenJobs.toolTipText=Increase this value if database locks cause problems. It gives a little more time for finalizing.
AIMIngestSettingsPanel.spSecondsBetweenJobs.toolTipText=Increase this value if database locks cause problems. It gives a little more time for finalizing.
AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title=Advanced Settings
AutoIngestSettingsPanel.examinerModeRadioButton.text=Examiner mode
AutoIngestSettingsPanel.autoIngestModeRadioButton.text=Auto Ingest mode
AutoIngestSettingsPanel.AdvancedAutoIngestSettingsPanel.Title=Advanced Settings
AutoIngestSettingsPanel.browseGlobalSettingsButton.text=Browse
AutoIngestSettingsPanel.CannotAccess=Cannot access
AutoIngestSettingsPanel.CheckPermissions=Check permissions.
AutoIngestSettingsPanel.EmptySettingsDirectory=Enter path to settings directory
AutoIngestSettingsPanel.ErrorSettingDefaultFolder=Error creating default folder
AutoIngestSettingsPanel.examinerModeRadioButton.text=Examiner mode
AutoIngestSettingsPanel.FileExportRules.text=File Export Rules
AutoIngestSettingsPanel.globalSettingsErrorTextField.text=
AutoIngestSettingsPanel.globalSettingsTextField.text=
@ -39,7 +38,6 @@ AutoIngestSettingsPanel.KeywordSearchNull=Cannot find Keyword Search service
AutoIngestSettingsPanel.MustRestart=Autopsy must be restarted for new configuration to take effect
AutoIngestSettingsPanel.nodePanel.TabConstraints.tabTitle=Node Configuration
AutoIngestSettingsPanel.NodeStatusLogging.text=Node Status Logging Settings
AutoIngestSettingsPanel.PathInvalid=Path is not valid
AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required to take effect.
AutoIngestSettingsPanel.restartRequiredLabel.text=Application restart required
AutoIngestSettingsPanel.ResultsDirectoryUnspecified=Shared cases folder must be set
@ -49,8 +47,39 @@ AutoIngestSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database po
AutoIngestSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number
AutoIngestSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number
AutoIngestSettingsPanel.validationErrMsg.MUdisabled=Multi user settings must be enabled and saved
AutoIngestSettingsPanel.bnTestMultiUser.text=Test
AutoIngestSettingsPanel.lbTestMultiUserText.text=Test Multi-User Case Creation and Ingest Settings
AutoIngestSettingsPanel.lbMultiUserResult.text=
AutoIngestSettingsPanel.lbTestResultText.text=
AutoIngestSettingsPanel.validationErrMsg.outputPathNotSpecified=Output folder must be set
AutoIngestSettingsPanel.PathInvalid=Case output directory path is not valid
AutoIngestSettingsPanel.CheckPermissions=Ensure that the user account {0} has write permissions in this folder
AutoIngestSettingsPanel.Success=Success
AutoIngestSettingsPanel.TestRunning=Test in progress...
AutoIngestSettingsPanel.servicesDown=Some of the Multi User services are down
GeneralOptionsPanelController.moduleErr.msg=A module caused an error listening to GeneralOptionsPanelController updates. See log to determine which module. Some data could be incomplete.
GeneralOptionsPanelController.moduleErr=Module Error
# {0} - errorMessage
MultiUserTestTool.criticalError=Critical error running data source processor on test data source: {0}
MultiUserTestTool.errorStartingIngestJob=Ingest manager error while starting ingest job
# {0} - cancellationReason
MultiUserTestTool.ingestCancelled=Ingest cancelled due to {0}
MultiUserTestTool.ingestSettingsError=Failed to analyze data source due to ingest settings errors
MultiUserTestTool.noContent=Test data source failed to produce content
# {0} - serviceName
MultiUserTestTool.serviceDown=Multi User service is down: {0}
MultiUserTestTool.startupError=Failed to analyze data source due to ingest job startup error
MultiUserTestTool.unableAddFileAsDataSource=Unable to add test file as data source to case
MultiUserTestTool.unableCreatFile=Unable to create a file in case output directory
# {0} - serviceName
MultiUserTestTool.unableToCheckService=Unable to check Multi User service state: {0}
MultiUserTestTool.unableToCreateCase=Unable to create case
MultiUserTestTool.unableToInitializeDatabase=Case database was not successfully initialized
MultiUserTestTool.unableToReadDatabase=Unable to read from case database
MultiUserTestTool.unableToReadTestFileFromDatabase=Unable to read test file info from case database
MultiUserTestTool.unableToRunIngest=Unable to run ingest on test data source
MultiUserTestTool.unableToUpdateKWSIndex=Unable to write to Keyword Search index
MultiUserTestTool.unexpectedError=Unexpected error while performing Multi User test
NodeStatusLogPanel.bnCancel.text=Cancel
NodeStatusLogPanel.bnOk.text=OK
NodeStatusLogPanel.bnTestDatabase.text=Test

View File

@ -0,0 +1,455 @@
/*
* 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.experimental.configuration;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import org.apache.commons.io.FileUtils;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseActionException;
import org.sleuthkit.autopsy.casemodule.CaseDetails;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import static org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback.DataSourceProcessorResult.CRITICAL_ERRORS;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TimeStampUtils;
import org.sleuthkit.autopsy.datasourceprocessors.AddDataSourceCallback;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSource;
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.casemodule.LocalFilesDSProcessor;
import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.core.ServicesMonitor;
import org.sleuthkit.autopsy.events.AutopsyEvent;
import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestJobStartResult;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleError;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.AbstractFile;
/**
* Test tool that creates a multi user case, database, KWS index, runs ingest,
* etc. If errors are encountered during this process, provides a message
* regarding the problem and possible causes.
*/
class MultiUserTestTool {
private static final String CASE_NAME = "Test_Multi_User_Settings";
private static final Logger LOGGER = Logger.getLogger(MultiUserTestTool.class.getName());
private static final String TEST_FILE_NAME = "AutopsyTempFile";
private static final Object INGEST_LOCK = new Object();
static final String MULTI_USER_TEST_SUCCESSFUL = NbBundle.getMessage(AutoIngestSettingsPanel.class, "AutoIngestSettingsPanel.Success");
private MultiUserTestTool() {
}
@NbBundle.Messages({
"MultiUserTestTool.unableToCreateCase=Unable to create case",
"MultiUserTestTool.unableToInitializeDatabase=Case database was not successfully initialized",
"MultiUserTestTool.unableToReadDatabase=Unable to read from case database",
"MultiUserTestTool.unableCreatFile=Unable to create a file in case output directory",
"MultiUserTestTool.unableAddFileAsDataSource=Unable to add test file as data source to case",
"MultiUserTestTool.unableToReadTestFileFromDatabase=Unable to read test file info from case database",
"MultiUserTestTool.unableToUpdateKWSIndex=Unable to write to Keyword Search index",
"MultiUserTestTool.unableToRunIngest=Unable to run ingest on test data source",
"MultiUserTestTool.unexpectedError=Unexpected error while performing Multi User test",
"# {0} - serviceName",
"MultiUserTestTool.serviceDown=Multi User service is down: {0}",
"# {0} - serviceName",
"MultiUserTestTool.unableToCheckService=Unable to check Multi User service state: {0}"
})
static String runTest(String rootOutputDirectory) {
// run standard tests for all services. this detects many problems sooner.
try {
if (!isServiceUp(ServicesMonitor.Service.REMOTE_CASE_DATABASE.toString())) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.serviceDown", ServicesMonitor.Service.REMOTE_CASE_DATABASE.getDisplayName());
}
} catch (ServicesMonitor.ServicesMonitorException ex) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService",
ServicesMonitor.Service.REMOTE_CASE_DATABASE.getDisplayName() + ". " + ex.getMessage());
}
try {
if (!isServiceUp(ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.toString())) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.serviceDown", ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.getDisplayName());
}
} catch (ServicesMonitor.ServicesMonitorException ex) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService",
ServicesMonitor.Service.REMOTE_KEYWORD_SEARCH.getDisplayName() + ". " + ex.getMessage());
}
try {
if (!isServiceUp(ServicesMonitor.Service.MESSAGING.toString())) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.serviceDown", ServicesMonitor.Service.MESSAGING.getDisplayName());
}
} catch (ServicesMonitor.ServicesMonitorException ex) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.unableToCheckService",
ServicesMonitor.Service.MESSAGING.getDisplayName() + ". " + ex.getMessage());
}
// Create a case in the output folder.
Case caseForJob;
try {
caseForJob = createCase(CASE_NAME, rootOutputDirectory);
} catch (CaseActionException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToCreateCase(), ex);
return Bundle.MultiUserTestTool_unableToCreateCase() + ". " + ex.getMessage();
}
if (caseForJob == null) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToCreateCase());
return Bundle.MultiUserTestTool_unableToCreateCase();
}
try {
// Verify that DB was created. etc
String getDatabaseInfoQuery = "select * from tsk_db_info";
try (SleuthkitCase.CaseDbQuery queryResult = caseForJob.getSleuthkitCase().executeQuery(getDatabaseInfoQuery)) {
ResultSet resultSet = queryResult.getResultSet();
// check if we got a result
if (resultSet.next() == false) {
// we got a result so we are able to read from the database
return Bundle.MultiUserTestTool_unableToInitializeDatabase();
}
} catch (TskCoreException | SQLException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToReadDatabase(), ex);
return Bundle.MultiUserTestTool_unableToReadDatabase() + ". " + ex.getMessage();
}
// Make a text file in Windows TEMP folder
String tempFilePath = System.getProperty("java.io.tmpdir") + TEST_FILE_NAME + "_" + TimeStampUtils.createTimeStamp() + ".txt";
try {
FileUtils.writeStringToFile(new File(tempFilePath), "Test", Charset.forName("UTF-8"));
} catch (IOException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableCreatFile(), ex);
return Bundle.MultiUserTestTool_unableCreatFile() + ". " + ex.getMessage();
}
// Add it as a logical file set data source.
AutoIngestDataSource dataSource = new AutoIngestDataSource("", Paths.get(tempFilePath));
try {
String error = runLogicalFilesDSP(caseForJob, dataSource);
if (!error.isEmpty()) {
LOGGER.log(Level.SEVERE, error);
return error;
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableAddFileAsDataSource(), ex);
return Bundle.MultiUserTestTool_unableAddFileAsDataSource() + ". " + ex.getMessage();
}
// Verify that Solr was able to create the core and is able to write to it
FileManager fileManager = caseForJob.getServices().getFileManager();
List<AbstractFile> listOfFiles = null;
try {
listOfFiles = fileManager.findFiles(new File(tempFilePath).getName());
if (listOfFiles == null || listOfFiles.isEmpty()) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToReadTestFileFromDatabase());
return Bundle.MultiUserTestTool_unableToReadTestFileFromDatabase();
}
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToReadTestFileFromDatabase(), ex);
return Bundle.MultiUserTestTool_unableToReadTestFileFromDatabase() + ". " + ex.getMessage();
}
AbstractFile file = listOfFiles.get(0);
// write to KWS index
KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class);
try {
kwsService.index(file);
} catch (TskCoreException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToUpdateKWSIndex(), ex);
return Bundle.MultiUserTestTool_unableToUpdateKWSIndex() + ". " + ex.getMessage();
}
// Run ingest on that data source and report errors if the modules could not start.
try {
String error = analyze(dataSource);
if (!error.isEmpty()) {
LOGGER.log(Level.SEVERE, error);
return error;
}
} catch (InterruptedException ex) {
LOGGER.log(Level.SEVERE, Bundle.MultiUserTestTool_unableToRunIngest(), ex);
return Bundle.MultiUserTestTool_unableToRunIngest() + ". " + ex.getMessage();
}
} catch (Exception ex) {
// unexpected exception firewall
LOGGER.log(Level.SEVERE, "Unexpected error while performing Multi User test", ex);
return Bundle.MultiUserTestTool_unexpectedError() + ". " + ex.getMessage();
} finally {
// Close and delete the case.
try {
Case.deleteCurrentCase();
} catch (CaseActionException ex) {
// I don't think this should result in the test being marked as "failed" if everyhitng else went well
LOGGER.log(Level.WARNING, "Unable to delete test case", ex);
}
}
return MULTI_USER_TEST_SUCCESSFUL;
}
/**
* Creates a new multi user case.
*
* @param baseCaseName Case name (will get time stamp appended to it)
* @param rootOutputDirectory Full path to directory in which the case will
* be created
* @return Case object
* @throws CaseActionException
*/
private static Case createCase(String baseCaseName, String rootOutputDirectory) throws CaseActionException {
String caseDirectoryPath = rootOutputDirectory + File.separator + baseCaseName + "_" + TimeStampUtils.createTimeStamp();
// Create the case directory
Case.createCaseDirectory(caseDirectoryPath, Case.CaseType.MULTI_USER_CASE);
CaseDetails caseDetails = new CaseDetails(baseCaseName);
Case.createAsCurrentCase(Case.CaseType.MULTI_USER_CASE, caseDirectoryPath, caseDetails);
return Case.getCurrentCase();
}
/**
* Passes the data source for the current job Logical Files data source
* processor that adds it to the case database.
*
* @param caseForJob The case
* @param dataSource The data source.
*
* @return Error String if there was an error, empty string if the data
* source was added successfully
*
* @throws InterruptedException if the thread running the job processing
* task is interrupted while blocked, i.e., if ingest is shutting down.
*/
@NbBundle.Messages({
"MultiUserTestTool.noContent=Test data source failed to produce content",
"# {0} - errorMessage",
"MultiUserTestTool.criticalError=Critical error running data source processor on test data source: {0}"
})
private static String runLogicalFilesDSP(Case caseForJob, AutoIngestDataSource dataSource) throws InterruptedException {
AutoIngestDataSourceProcessor selectedProcessor = new LocalFilesDSProcessor();
DataSourceProcessorProgressMonitor progressMonitor = new DoNothingDSPProgressMonitor();
synchronized (INGEST_LOCK) {
UUID taskId = UUID.randomUUID();
caseForJob.notifyAddingDataSource(taskId);
DataSourceProcessorCallback callBack = new AddDataSourceCallback(caseForJob, dataSource, taskId, INGEST_LOCK);
caseForJob.notifyAddingDataSource(taskId);
selectedProcessor.process(dataSource.getDeviceId(), dataSource.getPath(), progressMonitor, callBack);
INGEST_LOCK.wait();
// at this point we got the content object(s) from the DSP.
// check whether the data source was processed successfully
if (dataSource.getContent().isEmpty()) {
return Bundle.MultiUserTestTool_noContent();
}
if ((dataSource.getResultDataSourceProcessorResultCode() == CRITICAL_ERRORS)) {
for (String errorMessage : dataSource.getDataSourceProcessorErrorMessages()) {
LOGGER.log(Level.SEVERE, "Critical error running data source processor on test data source: {0}", errorMessage);
}
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.criticalError", dataSource.getDataSourceProcessorErrorMessages().get(0));
}
return "";
}
}
/**
* Analyzes the data source content returned by the data source processor
* using the configured set of data source level and file level analysis
* modules.
*
* @param dataSource The data source to analyze.
*
* @return Error String if there was an error, empty string if the data
* source was analyzed successfully
*
* @throws InterruptedException if the thread running the job processing
* task is interrupted while blocked, i.e., if auto ingest is shutting down.
*/
@NbBundle.Messages({
"# {0} - cancellationReason",
"MultiUserTestTool.ingestCancelled=Ingest cancelled due to {0}",
"MultiUserTestTool.startupError=Failed to analyze data source due to ingest job startup error",
"MultiUserTestTool.errorStartingIngestJob=Ingest manager error while starting ingest job",
"MultiUserTestTool.ingestSettingsError=Failed to analyze data source due to ingest settings errors"
})
private static String analyze(AutoIngestDataSource dataSource) throws InterruptedException {
LOGGER.log(Level.INFO, "Starting ingest modules analysis for {0} ", dataSource.getPath());
IngestJobEventListener ingestJobEventListener = new IngestJobEventListener();
IngestManager.getInstance().addIngestJobEventListener(ingestJobEventListener);
try {
synchronized (INGEST_LOCK) {
IngestJobSettings ingestJobSettings = new IngestJobSettings(AutoIngestUserPreferences.getAutoModeIngestModuleContextString());
List<String> settingsWarnings = ingestJobSettings.getWarnings();
if (settingsWarnings.isEmpty()) {
IngestJobStartResult ingestJobStartResult = IngestManager.getInstance().beginIngestJob(dataSource.getContent(), ingestJobSettings);
IngestJob ingestJob = ingestJobStartResult.getJob();
if (null != ingestJob) {
/*
* Block until notified by the ingest job event
* listener or until interrupted because auto ingest
* is shutting down.
*/
INGEST_LOCK.wait();
LOGGER.log(Level.INFO, "Finished ingest modules analysis for {0} ", dataSource.getPath());
IngestJob.ProgressSnapshot jobSnapshot = ingestJob.getSnapshot();
for (IngestJob.ProgressSnapshot.DataSourceProcessingSnapshot snapshot : jobSnapshot.getDataSourceSnapshots()) {
if (!snapshot.isCancelled()) {
List<String> cancelledModules = snapshot.getCancelledDataSourceIngestModules();
if (!cancelledModules.isEmpty()) {
LOGGER.log(Level.WARNING, String.format("Ingest module(s) cancelled for %s", dataSource.getPath()));
for (String module : snapshot.getCancelledDataSourceIngestModules()) {
LOGGER.log(Level.WARNING, String.format("%s ingest module cancelled for %s", module, dataSource.getPath()));
}
}
LOGGER.log(Level.INFO, "Analysis of data source completed");
} else {
LOGGER.log(Level.WARNING, "Analysis of data source cancelled");
IngestJob.CancellationReason cancellationReason = snapshot.getCancellationReason();
if (IngestJob.CancellationReason.NOT_CANCELLED != cancellationReason && IngestJob.CancellationReason.USER_CANCELLED != cancellationReason) {
return NbBundle.getMessage(MultiUserTestTool.class, "MultiUserTestTool.ingestCancelled", cancellationReason.getDisplayName());
}
}
}
} else if (!ingestJobStartResult.getModuleErrors().isEmpty()) {
for (IngestModuleError error : ingestJobStartResult.getModuleErrors()) {
LOGGER.log(Level.SEVERE, String.format("%s ingest module startup error for %s", error.getModuleDisplayName(), dataSource.getPath()), error.getThrowable());
}
LOGGER.log(Level.SEVERE, "Failed to analyze data source due to ingest job startup error");
return Bundle.MultiUserTestTool_startupError();
} else {
LOGGER.log(Level.SEVERE, String.format("Ingest manager ingest job start error for %s", dataSource.getPath()), ingestJobStartResult.getStartupException());
return Bundle.MultiUserTestTool_errorStartingIngestJob();
}
} else {
for (String warning : settingsWarnings) {
LOGGER.log(Level.SEVERE, "Ingest job settings error for {0}: {1}", new Object[]{dataSource.getPath(), warning});
}
return Bundle.MultiUserTestTool_ingestSettingsError();
}
}
} finally {
IngestManager.getInstance().removeIngestJobEventListener(ingestJobEventListener);
}
// ingest completed successfully
return "";
}
/**
* Tests service of interest to verify that it is running.
*
* @param serviceName Name of the service.
*
* @return True if the service is running, false otherwise.
*
* @throws ServicesMonitorException if there is an error querying the
* services monitor.
*/
private static boolean isServiceUp(String serviceName) throws ServicesMonitor.ServicesMonitorException {
return (ServicesMonitor.getInstance().getServiceStatus(serviceName).equals(ServicesMonitor.ServiceStatus.UP.toString()));
}
/**
* A data source processor progress monitor does nothing. There is currently
* no mechanism for showing or recording data source processor progress
* during an ingest job.
*/
private static class DoNothingDSPProgressMonitor implements DataSourceProcessorProgressMonitor {
/**
* Does nothing.
*
* @param indeterminate
*/
@Override
public void setIndeterminate(final boolean indeterminate) {
}
/**
* Does nothing.
*
* @param progress
*/
@Override
public void setProgress(final int progress) {
}
/**
* Does nothing.
*
* @param text
*/
@Override
public void setProgressText(final String text) {
}
}
/**
* An ingest job event listener that allows the job processing task to block
* until the analysis of a data source by the data source level and file
* level ingest modules is completed.
* <p>
* Note that the ingest job can spawn "child" ingest jobs (e.g., if an
* embedded virtual machine is found), so the job processing task must
* remain blocked until ingest is no longer running.
*/
private static class IngestJobEventListener implements PropertyChangeListener {
/**
* Listens for local ingest job completed or cancelled events and
* notifies the job processing thread when such an event occurs and
* there are no "child" ingest jobs running.
*
* @param event
*/
@Override
public void propertyChange(PropertyChangeEvent event) {
if (AutopsyEvent.SourceType.LOCAL == ((AutopsyEvent) event).getSourceType()) {
String eventType = event.getPropertyName();
if (eventType.equals(IngestManager.IngestJobEvent.COMPLETED.toString()) || eventType.equals(IngestManager.IngestJobEvent.CANCELLED.toString())) {
synchronized (INGEST_LOCK) {
INGEST_LOCK.notifyAll();
}
}
}
}
};
}

View File

@ -1,20 +1,20 @@
/*! \page content_viewer_page Content Viewer
The Content Viewer lives in the lower right-hand side of the Autopsy main screen and shows pictures, video, hex, text, extracted strings, metadata, etc. The Content Viewer is enabled when you select an entry in the \ref ui_results.
The Content Viewer lives in the lower right-hand side of the Autopsy main screen and shows pictures, video, hex, text, extracted strings, metadata, etc. The Content Viewer is populated when you select an entry in the \ref ui_results.
The Content Viewer is context-aware, meaning different tabs will be enabled depending on the type of content selected and which ingest modules have been run. It will default to what it considers the "most specific" tab. For example, selecting a JPG will cause the Content Viewer to automatically select the "Application" tab and will display the image there. If you instead would like the Content Viewer to stay on the previously selected tab when you change to a different content object, go to the \ref view_options_page panel through Tools->Options->Application Tab and select the "Stay on the same file viewer" option.
\image html content_viewer_options_panel.png
When a Result type is selected in the Result Viewer (as opposed to a file), most of the tabs will correspond to the file associated with the result and not the result itself. For example, when selecting a Keyword Hit, the "Hex", "Strings", and "File Metadata" tabs will show data from the file where the keyword was found. The descriptions below will generally assume a file has been selected, but most also apply when we have a file associated with a selected result.
When a result item is selected in the Result Viewer (as opposed to a file), most of the tabs will correspond to the file associated with the result and not the result itself. For example, when selecting a keyword hit, the "Hex", "Strings", and "File Metadata" tabs will show data from the file where the keyword was found. The descriptions below will generally assume a file has been selected, but most also apply when we have a file associated with a selected result.
\section cv_hex Hex
The Hex Content Viewer is nearly always available and shows you the raw and exact contents of a file. In this content viewer, the data of the file is represented as hexadecimal values grouped in 2 groups of 8 bytes, followed by one group of 16 ASCII characters which are derived from each pair of hex values (each byte). Non-printable ASCII characters and characters that would take more than one character space are typically represented by a dot (".") in the following ASCII field.
The Hex tab is nearly always available and shows you the raw and exact contents of a file. In this tab, the data of the file is represented as hexadecimal values grouped in 2 groups of 8 bytes, followed by one group of 16 ASCII characters which are derived from each pair of hex values (each byte). Non-printable ASCII characters and characters that would take more than one character space are typically represented by a dot (".") in the following ASCII field.
\image html content_viewer_hex.png
If desired, you can open the file in an external hex editor. This is configured through the "External Viewer" tab on the options panel. HxD has been tested to work, but alternate hex editors may also be compatible.
If desired, you can open the file in an external hex editor. This is configured through the "External Viewer" tab on the options panel. HxD has been verified to work with Autopsy, but alternate hex editors may also be compatible.
\image html content_viewer_hex_editor_setup.png
@ -22,12 +22,30 @@ Note that this process saves the file to disk before launching the hex editor. A
\image html content_viewer_hxd_progress.png
\section cv_strings Strings
\section cv_text Text
The Strings tab shows all text strings found in the file. Different scripts can be chosen from the drop-down menu to display results for non-Latin alphabets.
The Text tab has three sub tabs for displaying the text contained in the selected item.
\subsection cv_strings Strings
The Strings tab shows all text strings found in the file for the given script selected in the upper right. By default Latin text is used.
\image html content_viewer_strings_latin.png
Different scripts can be chosen from the drop-down menu to display results for non-Latin alphabets.
\image html content_viewer_strings_cyrillic.png
\subsection cv_indexed_text Indexed Text
The Indexed Text tab shows the text that has been indexed by the \ref keyword_search_page. You can switch the "Text Source" field to "Result Text" to see the text that has been indexed for the results associated with a file.
\image html content_viewer_indexed_text.png
\subsection cv_translation Translation
If you have a translation service enabled, the Translation tab allows you to translate the text. See the \ref machine_translation_page page for more information.
\section cv_app Application
For certain file types, the Application tab can display the contents in a user friendly format. The following screenshots show some examples of what the Application tab will display.
@ -48,11 +66,9 @@ HTML files can be displayed closer to their original form:
\image html content_viewer_html.png
\section cv_indexed_text Indexed Text
Registry hive files can be viewed in a format similar to a registry editor.
The Indexed Text tab shows the text that has been indexed by the Keyword Search module. You can switch the "Text Source" Field to "Result Text" to see which text has been indexed for associated results.
\image html content_viewer_indexed_text.png
\image html content_viewer_registry.png
\section cv_message Message
@ -68,7 +84,7 @@ The File Metadata tab displays basic information about the file, such as type, s
\section cv_results Results
The Results tab is active when selecting entries that are part of the Results tree, such as keyword hits, call logs, and messages. It is also active when looking at a file that has results associated with it. The exact fields displayed depend on the type of entry. The two images below show the Results tab for a call log and a web bookmark.
The Results tab is active when selecting items with associated results such as keyword hits, call logs, and messages. The exact fields displayed depend on the type of result. The two images below show the Results tab for a call log and a web bookmark.
\image html content_viewer_results_call.png
<br>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 KiB

After

Width:  |  Height:  |  Size: 293 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 251 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 431 KiB

After

Width:  |  Height:  |  Size: 277 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View File

@ -4,10 +4,10 @@ A central Solr server is needed to store keyword indexes, and its embedded Zooke
\section install_solr_prereq Prerequisites
You will need:
- 64-bit version of the Java Runtime Environment (JRE) from http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html.
- Download the Apache Solr 4.10.3-0 installation package from https://sourceforge.net/projects/autopsy/files/CollaborativeServices/Solr or Direct Download Link
- A 64-bit version of the Java Runtime Environment (JRE) from http://www.oracle.com/technetwork/java/javase/downloads/jre8-downloads-2133155.html.
- The Apache Solr 4.10.3-0 installation package from https://sourceforge.net/projects/autopsy/files/CollaborativeServices/Solr or Direct Download Link
- Access to an installed version of Autopsy so that you can copy files from it.
- A network-accessible machine to install Solr upon. Note that the Solr process will need to write data out to the main shared storage drive, and needs adequate permissions to write to this location, which may be across a network.
- A network-accessible machine to install Solr on. Note that the Solr process will need to write data out to the main shared storage drive, and needs adequate permissions to write to this location, which may be across a network.
\section install_solr_install Installation
@ -29,7 +29,7 @@ The following steps will configure Solr to run using an account that will have a
\subsection install_solr_config Solr Configuration
1. Stop the _solrJetty_ service by pressing _Start_, typing _services.msc_, pressing _Enter_, and locating the _solrJetty_ Windows service. Select the service and press _Stop the service_. If the service is already stopped and there is no _Stop the service_ available, this is okay.
2. Edit the <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\scripts\serviceinstall.bat"</i> script. You need administrator permission to change this file. The easiest way around this is to save a copy on the Desktop, edit the Desktop version, and copy the new one back over the top of the old. Windows will ask for permission to overwrite the old file; allow it. You should make the following changes to this file:
2. Edit the <i>"C:\Bitnami\solr-4.10.3-0\apache-solr\scripts\serviceinstall.bat"</i> script. You need administrator rights to change this file. The easiest way around this is to save a copy on the Desktop, edit the Desktop version, and copy the new one back over the top of the old. Windows will ask for permission to overwrite the old file; allow it. You should make the following changes to this file:
<br>
<br>
- Add the following options in the line that begins with <i>"C:\Bitnami\solr-4.10.3-0/apache-solr\scripts\prunsrv.exe"</i> :

View File

@ -0,0 +1,37 @@
/*! \page machine_translation_page Machine Translation
You can configure a machine translation service to use with Autopsy. If one is configured, you will be able to translate text in the \ref content_viewer_page and file names in the \ref result_viewer_page and \ref tree_viewer_page.
\section mt_config Configuration
To set up a machine translation service, go to Options->Tools and then select the Machine Translation tab. Select the service you want to use from the drop down menu at the top.
\image html mt_config.png
Each service will require slightly different configuration steps. After setting everything up, you can run a quick check that the service is set up correctly using the "Test" button.
\section mt_file_names Translating File Names
You can use machine translation to automatically translate file and folder names, such as the ones seen below:
\image html mt_file_name_original.png
To enable file name translation, go to the \ref view_options_page and check the box under "Translate Text".
\image html mt_file_name_enable.png
Once enabled, the translated versions of the file and folder names will be shown in the \ref tree_viewer_page and in the first column of the \ref result_viewer_page. The original name will be displayed in the new "Original Name" column.
\image html mt_file_names_translated.png
\section mt_content_viewer Translating File Content
After you set up a machine translation service, the Translation tab under the Text tab in the Content Viewer will be active. The Translation tab allows you to use your service to translate the beginning of a file. For example, you might see the following in the default Indexed Text tab:
\image html mt_content_viewer_untranslated_text.png
Switching to the Translation tab will display the results of running the text through the machine translation service.
\image html mt_content_viewer_translated.png
*/

View File

@ -49,6 +49,7 @@ The following topics are available here:
- \subpage common_properties_page
- \subpage search_all_cases_page
- \subpage logs_and_output_page
- \subpage machine_translation_page
- Reporting
- \subpage tagging_page
- \subpage reporting_page

View File

@ -9,7 +9,7 @@ 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 because he shouldn't see them or the originals are too big.
<li>Alice creates a portable case which will contain only her tagged files and results, plus any files associated with those results, and sends it to Bob.
<li>Alice creates a portable case which will contain only her tagged files and results, plus any files associated with those results, and sends it to Bob. She could also choose to include \ref interesting_files_identifier_page "interesting files" or results.
<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>
@ -21,25 +21,38 @@ The portable version could like this:
\image html portable_case_portable_version.png
Alice only tagged eight files and results, so most of the original content is no longer in the case. Some of the data sources had no tagged items so they're not included at all. The file structure of any tagged files is preserved - you can see that the tagged image in the screenshot is still in the same location, but the non-tagged files are gone. Note that although the original images (such as "image1.vhd") appear in the tree, their contents are not included in the portable case.
Alice only tagged eight files and results and her case had no interesting items, so most of the original content is no longer in the case. Some of the data sources had no tagged items so they're not included at all. The file structure of any tagged files is preserved - you can see that the tagged image in the screenshot is still in the same location, but the non-tagged files are gone. Note that although the original images (such as "image1.vhd") appear in the tree, their contents are not included in the portable case.
\section portable_case_creation Creating a Portable Case
First you'll want to make sure that all the files and results you want included in the portable case are tagged - see the \ref tagging_page page for more details.
You can see what tags you've added in the \ref tree_viewer_page.
A portable case can contain tagged files and results and data from the Interesting Items section of the \ref tree_viewer_page. You'll be able to choose which of the Interesting Item sets you want to include in the portable case.
\image html portable_case_interesting_items.png
You can tag any additional files you want to include in the portable case. See the \ref tagging_page page for details on how to create tags. You can see what tags you've added in the \ref tree_viewer_page.
\image html portable_case_tags.png
Portable cases are created through the \ref reporting_page feature. The Generate Report dialog will display a list of all tags that are in use in the current case and you can choose which ones you would like to include. At the bottom you can select the output folder for the new case. By default it will be placed in the "Reports" folder in the current case.
Portable cases are created through the \ref reporting_page feature. The Generate Report dialog will display a list of all tags and interesting file sets that are in use in the current case and you can choose which ones you would like to include. At the bottom you can choose to optionally package the case. Choosing to package the case without chunking will simply compress the portable case in a single archive that can be extracted with common compression programs. If you choose split the packaged case into multiple files, you will need to use the "Unpackage Portable Case" option before loading it. This will be discussed in the next section.
The portable case will be placed in the "Reports" folder in the current case.
\image html portable_case_report_panel.png
Here you can see the new portable case. It will be named with the original case name plus "(Portable)". The portable case is initially missing many of the normal Autopsy folders - these will be created the first time a user opens it. The portable case folder can be zipped and sent to a different user.
Here you can see an unpackaged portable case. It will be named with the original case name plus "(Portable)". The portable case is initially missing many of the normal Autopsy folders - these will be created the first time a user opens it.
\image html portable_case_folder.png
If you packaged the portable case but did not choose to split it into chunks, you'll have a single .zip file. If you chose to split the packaged case, you'll have one or more files starting with extension .zip.001.
\image html portable_case_chunks.png
\section portable_case_usage Using a Portable Case
If your portable case was packaged, you'll first need to unpackage it. Open the "Case" menu and then select "Unpackage Portable Case". This will bring up a dialog where you can browse to your packaged case and select where to extract it to. Once unpackaged you can open it normally.
\image html portable_case_unpackage.png
Portable cases generally behave like any other Autopsy case. You can run ingest, do keyword searches, use the timeline viewer, etc. One point to note is that while the original data source names appear in the case, the data sources themselves were not copied into the portable case.
\image html portable_case_empty_image.png

View File

@ -64,13 +64,17 @@ show up as Hashset Hits.
\subsection report_case_uco CASE-UCO
This module creates an JSON output file in <a href="https://github.com/ucoProject/CASE/wiki">CASE-UCO</a> format from a single data source.
This module creates a JSON output file in <a href="https://github.com/ucoProject/CASE/wiki">CASE-UCO</a> format for a single data source.
\image html reports_case.png
\subsection report_files Files - Text
This report module allows you create a tab delimited text file from all files in the current case. You can select which fields should be exported.
This report module allows you create a tab or comma delimited text file report of all of the files in the current case. Start by selecting which delimiter you would like to use.
\image html reports_files_delimiter.png
You can then select which fields should be reported.
\image html reports_files_config.png
<br>
@ -84,7 +88,7 @@ This report module generates a KML file from any GPS data in the case. This file
\subsection report_portable_case Portable Case
This report module generates a new Autopsy case from any tagged files and results. See the \ref portable_case_page page for additional information.
This report module generates a new Autopsy case that includes tagged and/or interesting items. See the \ref portable_case_page page for additional information.
\subsection report_stix STIX

View File

@ -1,37 +1,61 @@
/*! \page result_viewer_page Result Viewer
The Result Viewer is located on the top right of the Autopsy screen. It shows lists of files and their corresponding attributes such as time, path, size, checksum, etc.
The Result Viewer is located on the top right of the Autopsy screen and shows the the contents of what was selected in the \ref tree_viewer_page.
<br>
\section result_viewer_table Table Viewers
The main table viewer in the "Listing" tab displays the contents of the current selection as a table with selected details (properties) of each item. For files, some examples of the properties that this viewer shows are: name, time (modified, changed, accessed, and created), size, flags (directory and meta), mode, user ID, group ID, metadata address, attribute address, and type (directory and meta). For other data types, the columns will be different. Click the "Table" tab to select this view.
The following shows the main table viewer when a folder is selected in the Data Source section of the \ref tree_viewer_page.
\image html result-viewer-example-1.PNG
<br>
By default, the first three columns after the file name in the results viewer are named "S", "C" and "O".
As mentioned above, a table viewer is context-aware which means it will show applicable columns for the data type selected. The following shows the data in the "Web Bookmarks" node in the \ref tree_viewer_page.
\image html result-viewer-example-3.PNG
\subsection result_viewer_sco SCO Columns
By default, the first three columns after the file name in a table viewer are named "S", "C" and "O".
\image html view_options_sco.png
These columns display the following:
These columns display the following information:
<ul>
<li> (S)core column - indicates whether the item is interesting or notable
<li> (S)core column - indicates whether the item is interesting or notable.
<ul>
<li>Displays a red icon if the file is a match for a notable hash set or has been tagged with a notable tag
<li>Displays a yellow icon if the file has an interesting item match or has been tagged with a non-notable tag
<li>Displays a red icon if the file is a match for a notable hashset or has been tagged with a notable tag.
<li>Displays a yellow icon if the file has an interesting item match or has been tagged with a non-notable tag.
</ul>
<li> (C)omment column - indicates whether the item has a comment in the Central Repository or has a comment associated with a tag
<li> (C)omment column - indicates whether the item has a comment in the Central Repository or has a comment associated with a tag.
<li> (O)ther occurrences column - indicates how many data sources in the Central Repository contain this item. The count will include the selected item.
</ul>
To display more information about why an icon has appeared, you can hover over it. The Comment and Other occurrences columns query the Central Repository. If this seems to be having a performance impact, it can be disabled through the \ref view_options_page. This will remove the Other occurrences column entirely and the Comment column will be based only on tags.
You can also switch it to Thumbnail view to see thumbnails of the content in the selected folder.
\subsection export_csv Exporting to CSV
<br>
\image html result-viewer-example-2.PNG
<br>
You can export the contents of a table viewer to a CSV file in two ways. The "Save table as CSV" button in the upper left will save the entire contents of the table viewer to a CSV file. You can also select rows in the table viewer and then right-click and select "Export selected rows to CSV" to save only a subset of the rows:
The Result Viewer is context-aware, meaning it will show applicable columns for the data type selected.
<br>
\image html result-viewer-example-3.PNG
<br>
\image html result_viewer_csv.PNG
\subsection right_click_functions Right Click Functions
Table viewers in the Results Viewer have certain right-click functions built-in into them that can be accessed when a row of a particular type is selected (a file, a directory, or a result).
Here are some examples that you may see:
\li Open File in External Viewer: Opens the selected file in an "external" application as defined by the local OS or through the External Viewer tab that you can navigate to by selecting the Options menu item from the Tools menu. For example, HTML files may be opened by Chrome or Firefox or some other browser, depending on what the local system is configured to use.
\li View in New Window: Opens the selected item in a new content viewer (instead of in the default location in the lower right area of the main window).
\li Extract: Makes a local copy of the selected file or directory for further analysis.
\section thumbnail_result_viewer Thumbnail Viewers
Thumbnail viewers display items selected in the \ref tree_viewer_page as a table of thumbnail images in adjustable sizes. This viewer only supports "picture" files (it currently only supports the JPG, GIF, and PNG formats). Click on the Thumbnail tab in the Listing tab to select this view. Note that for a large number of images in a directory selected in the Data Sources area of the \ref tree_viewer_page, or for a selection in the Views area of the \ref tree_viewer_page that contains a large number of images, it might take a while to populate the thumbnail viewer for the first time, i.e., before the thumbnails are cached.
\image html thumbnail-result-viewer-tab.PNG
\section result_viewer_paging Paging
A table viewer can perform slowly when displaying a large numbers of rows. To address this, when there are over a certain numer of rows (10,000 by default), the results will be split into pages. The paging controls at the top right of the table view allow you to browse the different pages.
\image html result_viewer_paging.PNG
You can adust the page sizes through \ref view_options_page or turn paging off entirely.
*/

View File

@ -1,6 +1,6 @@
/*! \page tagging_page Tagging
Tagging (or Bookmarking) allows you to create a reference to a file or object and easily find it later. Tagging is also used by the \ref central_repo_page "central repository" to mark items as notable.
Tagging (or Bookmarking) allows you to create a reference to a file or object and easily find it later or include it in a \ref reporting_page "report". For images, you can select a portion of the image to tag. Tagging is also used by the \ref central_repo_page "central repository" to mark items as notable.
\section tagging_items Tagging items
@ -41,6 +41,40 @@ Tagged results are shown in the "Results" portion of the tree under "Tags". Tagg
\image html tagging-4.PNG
\section image_tagging Image tagging
When you have an image selected in the \ref result_viewer_page, you'll see a "Tags Menu" option in the upper right of the "Application" \ref content_viewer_page "Content Viewer". This allows you to tag only a selected area of the image.
\image html tagging_image_menu.png
\subsection image_tagging_creation Creating and editing an image tag
To start, select the "Create" option on the tags menu. Then left-click and hold to draw a box around part of the image. When you release the mouse, you'll be able to choose which tag name to use.
\image html tagging_image_select.png
You can add a new tag name using the "New Tag" button.
\image html tagging_image_create_tag.png
Once you choose the tag name you'll see a red outline in the image around the section you chose. If you need to edit the tag, right click on the red border to select it. From here you can drag the edges to resize the box, or delete it by selecting "Delete" from the tags menu.
\image html tagging_image_edit_tag.png
You can create multiple tags in the same image.
\image html tagging_image_multiple.png
If you want to temporarily hide the tag outlines, select "Hide" from the tags menu. You can then select "Show" to see them again. The outlines will also reappear if you switch to a different item in the Result Viewer and come back.
\subsection image_tagging_report Exporting and reporting on image tags
If you want to save the image with the tag outline, select "Export" from the tags menu. The result will always be a PNG file. Note that using the "Extract File(s)" option from the right-click menu in the Result Viewer will export the original image.
You'll also be able to see the image tags in an \ref report_html "HTML report".
\image html tagging_image_report.png
\section managing_tags Managing tags
The list of tags can be edited through the Tags tab on the Options menu.

View File

@ -1,8 +1,47 @@
/*! \page tree_viewer_page Tree Viewer
The Tree Viewer shows the discovered folders by the data sources they come from, as well as a list of files in the folders. It is located on the left side of the Autopsy screen. The "Group by Data Source" option on the top left moves all views, results, and tags under their corresponding data source.
The tree on the left-hand side of the main window is where you can browse the files in the data sources in the case and find saved results from automated analyis (ingest). The tree has five main areas:
- <b>Data Sources:</b> This shows the directory tree hierarchy of the data sources. You can navigate to a specific file or directory here. Each data source added to the case is represented as a distinct sub tree. If you add a data source multiple times, it shows up multiple times.
- <b>Views:</b> Specific types of files from the data sources are shown here, aggregated by type or other properties. Files here can come from more than one data source.
- <b>Results:</b> This is where you can see the results from both the automated analysis (ingest) running in the background and your search results.
- <b>Tags:</b> This is where files and results that have been \ref tagging_page "tagged" are shown.
- <b>Reports:</b> Reports that you have generated, or that ingest modules have created, show up here.
Each folder in the tree on the left shows how many items are contained within it in parentheses after the directory name. See the picture below.
You can also use the "Group by data source" option available through the \ref view_options_page to move the Views, Results, and Tags tree nodes under their corresponding data sources. This can be helpful on very large cases to reduce the size of each sub tree. For example:
\image html ui_layout_group_tree.PNG
\section ui_tree_ds Data Sources
The Data Sources area shows each data source that has been added to the case, in order added (top one is first).
Right clicking on the various nodes in the Data Sources area of the tree will allow you to get more options for each data source and its contents.
Unallocated space is the chunks of a file system that are currently not being used for anything. Unallocated space can hold deleted files and other interesting artifacts. In an image data source, unallocated space is stored in blocks with distinct locations in the file system. However, because of the way carving tools work, it is better to feed these tools a single, large unallocated space file. Autopsy provides access to both methods of looking at unallocated space.
\li <b>Individual blocks in a volume</b> For each volume, there is a "virtual" folder named "$Unalloc". This folder contains all the individual unallocated blocks in contiguous runs (unallocated space files) as the image is storing them. You can right click and extract any unallocated space file the same way you can extract any other type of file in the Data Sources area.
\li <b>Single files</b> Right click on a volume and select "Extract Unallocated Space as Single File" to concatenate all of the unallocated space files in the volume into a single, continuous file. (If desired, you can right click on an image, and select "Extract Unallocated Space to Single Files" which will do the same thing, but once for each volume in the image).
An example of the single file extraction option is shown below.
\image html extracting-unallocated-space.PNG
\section ui_tree_views Views
Views filter all the files in the case by some property of the file.
- <b>File Types</b> Sorts files by file extension or by MIME type, and shows them in the appropriate group. For example, files with .mp3 and .wav extensions end up in the "Audio" group.
- <b>Deleted Files</b> Displays files that have been deleted, but the names have been recovered.
- <b>File Size</b> Sorts files based on size.
\section ui_tree_results Results
- <b>Extracted Content:</b> Many ingest modules will place results here; EXIF metadata, GPS locations, or Web history for example.
- <b>Keyword Hits:</b> Keyword search hits show up here.
- <b>Hashset Hits:</b> Hashset hits show up here.
- <b>E-Mail Messages:</b> Email messages show up here.
- <b>Interesting Items:</b> Things deemed interesting show up here.
- <b>Accounts:</b> Credit card accounts show up here.
- <b>Tags:</b> Any item you tag shows up here so you can find it again easily.
\section ui_tree_reports Reports
Reports can be added by \subpage ingest_page or created using the \subpage reporting_page tool.
\image html directory-tree.PNG
*/

View File

@ -5,115 +5,37 @@
\section ui_overview Overview
The major areas in the Autopsy User Interface (UI) are:
- \ref ui_tree, shown outlined in green below
- \ref ui_results, shown outlined in blue below
- \ref ui_content, shown outlined in red below
- \ref ui_keyword, shown outlined in yellow below
- \ref ui_status, shown in solid purple below
- \ref ui_tree, shown in green on the left side
- \ref ui_results, shown in blue on the upper right side
- \ref ui_content, shown in red on the lower right side
- \ref ui_keyword, shown in magenta in the upper right corner
- \ref ui_status, shown in purple in the lower right corner
You can customize how data is shown in the UI through the \ref view_options_page panel.
\image html ui-layout-1.PNG
<br>
<br>
<br>
\section ui_tree Tree Viewer
\subpage tree_viewer_page "More..."
<br>
The Tree Viewer on the left-hand side is the top level of the UI. Selecting items in the Tree Viewer will cause their contents to be displayed in the Result Viewer to the right. You can browse the files in the image, find saved results generated by the \ref ingest_page "ingest modules", and see the results from \ref tagging_page and \ref reporting_page. See the \subpage tree_viewer_page page for additional information.
The tree on the left-hand side is where you can browse the files in the image and find saved results from automated procedures (ingest). The tree has five main areas:
- <b>Data Sources:</b> This shows the directory tree hierarchy of the file systems in the images. You can navigate to a specific file or directory here. Each data source added is represented as a drive. If you add a data source multiple times, it shows up multiple times.
- <b>Views:</b> Specific types of files from the data sources are shown here, aggregated by type or other properties. Files here can come from more than one data source. Look here for files of a specific type or property.
- <b>Results:</b> Where you can see the results from the background ingest tasks and you can see your previous search results. Go here to see what was found by the ingest modules and to find your previous search results.
- <b>Tags:</b> Where files and results that have been \ref tagging_page "tagged" are shown
- <b>Reports:</b> References to reports that you have generated or that ingest modules have created show up here
You can also use the "Group by data source" option available through the \ref view_options_page to move the views, results, and tags subtrees under their corresponding data sources. This can be helpful on very large cases to reduce the size of each node.
\image html ui_layout_group_tree.PNG
\subsection ui_tree_ds Data Sources
The Data Sources section shows each data source that has been added to the case, in order added (top one is first).
Right clicking on the various nodes in the Data Sources section of the tree will allow you to get more options for each data source and its contents.
Unallocated space is chunks of the file system that is currently not being used for anything. Unallocated space can store deleted files and other interesting artifacts. On the actual image, Unallocated space is stored in blocks with distinct locations on the system. However, because of the way various carving tools work, it is more ideal to feed them a single, large unallocated file. Autopsy provides access to both methods of looking at unallocated space.
\li <b>Individual blocks in a volume</b> There is a folder named "Unalloc". This folder contains all the individual unallocated blocks as the image is storing them. You can right click and extract them the same way you can extract any other type of file in the Directory Tree.
\li <b>Single files</b> Right click on a volume and select "Extract Unallocated Space as Single File" to concatenate all the unallocated files in the volume into a single, continuous file. (If desired, you can right click on an image, and select "Extract Unallocated Space to Single Files" which will do the same thing, but once for each volume in the image).
An example of the single file extraction option is shown below.
\image html extracting-unallocated-space.PNG
\subsection ui_tree_views Views
Views filter all the files in the case by some external property of the file, not by any internal analysis of the file.
- <b>File Type</b> Sorts files by file extension or MIME type, and shows them in the appropriate group. For example, .mp3 and .wav both end up in the "Audio" group.
- <b>Recent Files</b> Displays files that are accessed within the last seven days the user had the device.
- <b>Deleted Files</b> Displays files that have been deleted but the names have been recovered.
- <b>File Size</b> Sorts files based upon size. This can give you an idea where to look for files you are interested in.
\subsection ui_tree_results Results
- <b>Extracted Content:</b> Many ingest modules will place results here; EXIF data, GPS locations, or Web History for example
- <b>Keyword Hits:</b> Keyword search hits show up here
- <b>Hashset Hits:</b> Hashset hits show up here
- <b>E-Mail Messages:</b> Email messages show up here
- <b>Interesting Items:</b> Things deemed interesting show up here
- <b>Accounts:</b> Credit card accounts show up here
- <b>Tags:</b> Any item you tag shows up here so you can find it again easily
\subsection ui_tree_reports Reports
Reports can be added by \subpage ingest_page or created using the \subpage reporting_page tool.
<br>
<br>
<br>
\section ui_results Result Viewer
\subpage result_viewer_page "More..."
<br>
The Result Viewer windows are in the upper right area of the interface and display the results from selecting something in the tree. You will have the option to display the results in a variety of formats.
\subsection right_click_functions Right Click Functions
Viewers in Result Viewers have certain right-click functions built-in into them that can be accessed when a node a certain type is selected (a file, directory or a result).
Here are some examples that you may see:
\li Open File in External Viewer: Opens the selected file in an "external" application as defined by the local OS or through the External Viewer tab on the Options menu. For example, HTML files may be opened by IE or Firefox, depending on what the local system is configured to use.
\li View in New Window: Opens the content in a new internal Content Viewer (instead of in the default location in the lower right).
\li Extract: Make a local copy of the file or directory for further analysis.
\li Search for files with the same MD5 Hash: Searches the entire file-system for any files with the same MD5 Hash as the one selected.
\subsection thumbnail_result_viewer Thumbnail Result Viewers
Thumbnail Results Viewer displays the data catalog as a table of thumbnail images in adjustable sizes. This viewer only supports picture files (Currently, only supports JPG, GIF, and PNG formats). Click the Thumbnail tab to select this view. Note that for a large number of images in a directory selected in the Data Explorer, or for a View selected that contains a large number of images, it might take a while to populate this view for the first time before the images are cached.
<b>Example</b>\n
Below is an example of "Thumbnail Results Viewer" window:
\image html thumbnail-result-viewer-tab.PNG
\subsection table_result_viewer Table Result Viewers
Table Results Viewer (Directory Listing) displays the data catalog as a table with some details (properties) of each file. The properties that it shows are: name, time (modified, changed, accessed, and created), size, flags (directory and meta), mode, user ID, group ID, metadata address, attribute address, and type (directory and meta). Click the Table Viewer tab to select this view.
The Results Viewer can be also activated for saved results and it can show a high level results grouped, or a results at a file level, depending on which node on the Directory Tree is selected to populate the Table Results Viewer.
<b>Example</b>\n
Below is an example of a "Table Results Viewer" window:
\image html table-result-viewer-tab.PNG
The Result Viewer windows are in the upper right area of the interface and display the results from selecting something in the Tree Viewer. The columns displayed will depend on what was selected in the Tree Viewer - files will show things like path, size, and creation date while a contact would show its name, phone number, and email. Selecting an item in the Result Viewer will show details about the item in the Content Viewer below. See the \ref result_viewer_page for additional information.
\section ui_content Content Viewer
The \ref content_viewer_page area is in the lower right area of the interface. This area is used to view a specific file in a variety of formats. There are different tabs for different viewers. Not all tabs support all file types, so only some of them will be enabled. To display data in this area, a file must be selected from the Result Viewer window.
The Content Viewer area is in the lower right area of the interface. This area is used to view a specific file in a variety of formats. There are different tabs for different viewers. Not all tabs support all file types, so only some of them will be enabled. To display data in this area, a file must be selected from the Result Viewer window.
The Content Viewer area is part of a plug-in framework. You can install modules that will add more viewer types. For additional information on the built-in content viewers, see the \ref content_viewer_page page.
The Content Viewer area is part of a plug-in framework, meaning you can install modules that will add more viewer types.
For additional information see the \ref content_viewer_page page.
\section ui_keyword Keyword Search
Keyword Search allows the user to search for keywords in the data source. It is covered in more detail here: \subpage keyword_search_page
The Keyword Search feature allows the user to search for keywords in one or more data sources contained in the current case. It is covered in more detail here: \ref keyword_search_page
\section ui_status Status Area
The Status area will show progress bars while ingest is occuring. This visually indicates to the user what portion of the processing is already complete. The user can click on the progress bars to see further detail or to cancel ingest jobs.
The Status area will show progress bars while ingest is occurring. This visually indicates what portion of the processing is already complete. You can click on the progress bars to see further detail or to cancel ingest jobs.
<br>
*/

View File

@ -39,6 +39,10 @@ This option allows you to hide tags from other users in the Tagging section of t
By default, the first three columns in the result viewer after the file name in the results viewer are named "S", "C" and "O". These are described in more detail on the \ref result_viewer_page page. The Comment and Other occurrences columns query the Central Repository. If this seems to be having a performance impact, it can be disabled using the checkbox. This will remove the Other occurrences column entirely and the Comment column will be based only on tags.
\subsection view_options_paging Paging
By default, only 10,000 results will be show in the Result Viewer. You can change that threshold here. Setting it to zero will disable paging.
\subsection view_options_content_viewer Content viewer selection
By default, the \ref content_viewer_page attempts to select the most relevant tab to display when choosing a node. If you would like to change this behavior to instead stay on the same content viewer when changing nodes, switch to the "Stay on the same file viewer" option.
@ -53,7 +57,7 @@ Timestamps can be viewed in either local time or in a time zone selected in the
\subsection view_options_translate Translate text
If you have a custom translation module installed, this option will add a column to the \ref result_viewer_page to show the translated name of files and folders.
If you have a \ref machine_translation_page module installed, this option will add a column to the \ref result_viewer_page to show the translated name of files and folders.
\section view_options_case Current Case Settings