Merge branch 'develop' of https://github.com/sleuthkit/autopsy into hashDatabase

This commit is contained in:
Nick Davis 2014-04-14 16:27:39 -04:00
commit 8fe3965524
223 changed files with 5320 additions and 4336 deletions

View File

@ -1,5 +1,10 @@
file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar
file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
file.reference.metadata-extractor-2.6.2.jar=release/modules/ext/metadata-extractor-2.6.2.jar
file.reference.sqlite-jdbc-3.8.0-SNAPSHOT.jar=release/modules/ext/sqlite-jdbc-3.8.0-SNAPSHOT.jar file.reference.sqlite-jdbc-3.8.0-SNAPSHOT.jar=release/modules/ext/sqlite-jdbc-3.8.0-SNAPSHOT.jar
file.reference.tika-core-1.2.jar=release/modules/ext/tika-core-1.2.jar
file.reference.Tsk_DataModel.jar=release/modules/ext/Tsk_DataModel.jar file.reference.Tsk_DataModel.jar=release/modules/ext/Tsk_DataModel.jar
file.reference.xmpcore.jar=release/modules/ext/xmpcore.jar
javac.source=1.7 javac.source=1.7
javac.compilerargs=-Xlint -Xlint:-serial javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt license.file=../LICENSE-2.0.txt

View File

@ -207,6 +207,26 @@
<package>org.sleuthkit.autopsy.report</package> <package>org.sleuthkit.autopsy.report</package>
<package>org.sleuthkit.datamodel</package> <package>org.sleuthkit.datamodel</package>
</public-packages> </public-packages>
<class-path-extension>
<runtime-relative-path>ext/jdom-2.0.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-2.0.5.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sevenzipjbinding.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmpcore.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmpcore.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jdom-2.0.5-contrib.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jdom-2.0.5-contrib.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin>
</class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/Tsk_DataModel.jar</runtime-relative-path> <runtime-relative-path>ext/Tsk_DataModel.jar</runtime-relative-path>
<binary-origin>release/modules/ext/Tsk_DataModel.jar</binary-origin> <binary-origin>release/modules/ext/Tsk_DataModel.jar</binary-origin>
@ -215,6 +235,14 @@
<runtime-relative-path>ext/sqlite-jdbc-3.8.0-SNAPSHOT.jar</runtime-relative-path> <runtime-relative-path>ext/sqlite-jdbc-3.8.0-SNAPSHOT.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.8.0-SNAPSHOT.jar</binary-origin> <binary-origin>release/modules/ext/sqlite-jdbc-3.8.0-SNAPSHOT.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/metadata-extractor-2.6.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/metadata-extractor-2.6.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/tika-core-1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-core-1.2.jar</binary-origin>
</class-path-extension>
</data> </data>
</configuration> </configuration>
</project> </project>

Binary file not shown.

Binary file not shown.

View File

@ -48,3 +48,4 @@ GetTagNameDialog.unableToAddTagNameToCase.msg=Unable to add the {0} tag name to
GetTagNameDialog.taggingErr=Tagging Error GetTagNameDialog.taggingErr=Tagging Error
GetTagNameDialog.tagNameAlreadyDef.msg=A {0} tag name has already been defined. GetTagNameDialog.tagNameAlreadyDef.msg=A {0} tag name has already been defined.
GetTagNameDialog.dupTagErr=Duplicate Tag Error GetTagNameDialog.dupTagErr=Duplicate Tag Error
OpenLogFolder.error1=Log File Not Found: {0}

View File

@ -0,0 +1,64 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 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.actions;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.modules.Places;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
@ActionID(
category = "Help",
id = "org.sleuthkit.autopsy.actions.OpenLogFolder")
@ActionRegistration(
displayName = "#CTL_OpenLogFolder")
@ActionReference(path = "Menu/Help", position = 1750)
@Messages("CTL_OpenLogFolder=Open Log Folder")
/**
* Action in menu to open the folder containing the log files
*/
public final class OpenLogFolderAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
File logDir = new File(Places.getUserDirectory().getAbsolutePath() + File.separator + "var" + File.separator + "log");
if (logDir.exists() == false) {
NotifyDescriptor d =
new NotifyDescriptor.Message(
java.text.MessageFormat.format(java.util.ResourceBundle.getBundle("org/sleuthkit/autopsy/actions/Bundle").getString("OpenLogFolder.error1"), new Object[]{logDir.getAbsolutePath()}),
NotifyDescriptor.ERROR_MESSAGE);
DialogDisplayer.getDefault().notify(d);
} else {
Desktop.getDesktop().open(logDir);
}
} catch (IOException ex) {
Exceptions.printStackTrace(ex);
}
}
}

View File

@ -108,7 +108,7 @@ public final class AddImageAction extends CallableSystemAction implements Presen
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
Logger.noteAction(AddImageAction.class); Logger.noteAction(AddImageAction.class);
if (IngestManager.getDefault().isIngestRunning()) { if (IngestManager.getInstance().isIngestRunning()) {
final String msg = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg"); final String msg = NbBundle.getMessage(this.getClass(), "AddImageAction.ingestConfig.ongoingIngest.msg");
if (JOptionPane.showConfirmDialog(null, msg, if (JOptionPane.showConfirmDialog(null, msg,
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),

View File

@ -163,7 +163,8 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
*/ */
@Override @Override
public void readSettings(WizardDescriptor settings) { public void readSettings(WizardDescriptor settings) {
JButton cancel = new JButton("Cancel"); JButton cancel = new JButton(
NbBundle.getMessage(this.getClass(), "AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text"));
cancel.setEnabled(false); cancel.setEnabled(false);
settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel}); settings.setOptions(new Object[]{WizardDescriptor.PREVIOUS_OPTION, WizardDescriptor.NEXT_OPTION, WizardDescriptor.FINISH_OPTION, cancel});
cleanupTask = null; cleanupTask = null;

View File

@ -4,7 +4,7 @@ CTL_CaseCloseAct=Close Case
CTL_CaseNewAction=New Case... CTL_CaseNewAction=New Case...
CTL_CasePropertiesAction=Case Properties... CTL_CasePropertiesAction=Case Properties...
CTL_OpenAction=Open Case... CTL_OpenAction=Open Case...
CTL_OpenRecentAction=Open Recent Case Menu/File/OpenRecentCase=Open Recent Case
CTL_CaseDeleteAction=Delete Case CTL_CaseDeleteAction=Delete Case
OpenIDE-Module-Name=Case OpenIDE-Module-Name=Case
NewCaseVisualPanel1.jLabel1.text_1=Enter New Case Information: NewCaseVisualPanel1.jLabel1.text_1=Enter New Case Information:
@ -230,3 +230,4 @@ XMLCaseManagement.open.msgDlg.notAutCase.msg=Error\: This is not an Autopsy conf
Detail\: \ Detail\: \
Cannot open a non-Autopsy config file (at {1}). Cannot open a non-Autopsy config file (at {1}).
XMLCaseManagement.open.msgDlg.notAutCase.title=Error XMLCaseManagement.open.msgDlg.notAutCase.title=Error
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel

View File

@ -4,7 +4,7 @@ CTL_CaseCloseAct=\u30B1\u30FC\u30B9\u3092\u9589\u3058\u308B
CTL_CaseNewAction=\u65B0\u898F\u30B1\u30FC\u30B9\u2026 CTL_CaseNewAction=\u65B0\u898F\u30B1\u30FC\u30B9\u2026
CTL_CasePropertiesAction=\u30B1\u30FC\u30B9\u30D7\u30ED\u30D1\u30C6\u30A3\u2026 CTL_CasePropertiesAction=\u30B1\u30FC\u30B9\u30D7\u30ED\u30D1\u30C6\u30A3\u2026
CTL_OpenAction=\u30B1\u30FC\u30B9\u3092\u958B\u304F\u2026 CTL_OpenAction=\u30B1\u30FC\u30B9\u3092\u958B\u304F\u2026
CTL_OpenRecentAction=\u6700\u8FD1\u958B\u3044\u305F\u30B1\u30FC\u30B9\u3092\u958B\u304F Menu/File/OpenRecentCase=\u6700\u8FD1\u958B\u3044\u305F\u30B1\u30FC\u30B9\u3092\u958B\u304F
CTL_CaseDeleteAction=\u30B1\u30FC\u30B9\u524A\u9664 CTL_CaseDeleteAction=\u30B1\u30FC\u30B9\u524A\u9664
OpenIDE-Module-Name=\u30B1\u30FC\u30B9 OpenIDE-Module-Name=\u30B1\u30FC\u30B9
NewCaseVisualPanel1.jLabel1.text_1=\u65B0\u898F\u30B1\u30FC\u30B9\u60C5\u5831\u3092\u5165\u529B\uFF1A NewCaseVisualPanel1.jLabel1.text_1=\u65B0\u898F\u30B1\u30FC\u30B9\u60C5\u5831\u3092\u5165\u529B\uFF1A
@ -59,10 +59,10 @@ MissingImageDialog.selectButton.text=\u30A4\u30E1\u30FC\u30B8\u3092\u9078\u629E
MissingImageDialog.titleLabel.text=\u6B20\u843D\u3057\u305F\u30A4\u30E1\u30FC\u30B8\u306E\u691C\u7D22 MissingImageDialog.titleLabel.text=\u6B20\u843D\u3057\u305F\u30A4\u30E1\u30FC\u30B8\u306E\u691C\u7D22
MissingImageDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB MissingImageDialog.cancelButton.text=\u30AD\u30E3\u30F3\u30BB\u30EB
LocalDiskPanel.errorLabel.text=\u30A8\u30E9\u30FC\u30E9\u30D9\u30EB LocalDiskPanel.errorLabel.text=\u30A8\u30E9\u30FC\u30E9\u30D9\u30EB
LocalFilesPanel.infoLabel.text=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u53CA\u3073\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u8FFD\u52A0\uFF1A LocalFilesPanel.infoLabel.text=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u53CA\u3073\u30D5\u30A9\u30EB\u30C0\u3092\u8FFD\u52A0\uFF1A
LocalFilesPanel.selectButton.text=\u8FFD\u52A0 LocalFilesPanel.selectButton.text=\u8FFD\u52A0
LocalFilesPanel.localFileChooser.dialogTitle=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u53C8\u306F\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u9078\u629E LocalFilesPanel.localFileChooser.dialogTitle=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u53C8\u306F\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u629E
LocalFilesPanel.selectButton.toolTipText=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u53CA\u3073\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u30ED\u30B8\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u3068\u3057\u3066\u8FFD\u52A0\u3057\u307E\u3059 LocalFilesPanel.selectButton.toolTipText=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u53CA\u3073\u30D5\u30A9\u30EB\u30C0\u3092\u30ED\u30B8\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u3068\u3057\u3066\u8FFD\u52A0\u3057\u307E\u3059
LocalFilesPanel.clearButton.text=\u30AF\u30EA\u30A2 LocalFilesPanel.clearButton.text=\u30AF\u30EA\u30A2
LocalFilesPanel.clearButton.toolTipText=\u73FE\u5728\u9078\u629E\u3055\u308C\u3066\u3044\u308B\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u304C\u30AF\u30EA\u30A2\u3055\u308C\u307E\u3059 LocalFilesPanel.clearButton.toolTipText=\u73FE\u5728\u9078\u629E\u3055\u308C\u3066\u3044\u308B\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u30D1\u30B9\u304C\u30AF\u30EA\u30A2\u3055\u308C\u307E\u3059
LocalFilesPanel.selectedPaths.toolTipText= LocalFilesPanel.selectedPaths.toolTipText=
@ -78,7 +78,7 @@ AddImageWizardChooseDataSourceVisual.nextLabel.text=<html> \u300C\u6B21\u3078\u3
AddImageWizardChooseDataSourceVisual.imgInfoLabel.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u60C5\u5831\u3092\u5165\u529B\uFF1A AddImageWizardChooseDataSourceVisual.imgInfoLabel.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u60C5\u5831\u3092\u5165\u529B\uFF1A
AddImageWizardAddingProgressVisual.progressLabel.text=\uFF1C\u30D7\u30ED\u30B0\u30EC\u30B9\uFF1E AddImageWizardAddingProgressVisual.progressLabel.text=\uFF1C\u30D7\u30ED\u30B0\u30EC\u30B9\uFF1E
AddImageWizardAddingProgressVisual.viewLogButton.text=\u30ED\u30B0\u3092\u8868\u793A AddImageWizardAddingProgressVisual.viewLogButton.text=\u30ED\u30B0\u3092\u8868\u793A
AddImageWizardAddingProgressVisual.titleLabel.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u8FFD\u52A0\u4E2D AddImageWizardAddingProgressVisual.titleLabel.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0\u4E2D
AddImageWizardAddingProgressVisual.subTitle1Label.text=\u30ED\u30FC\u30AB\u30EB\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u60C5\u5831\u3092\u8FFD\u52A0\u4E2D\u3067\u3059\u3002\u3053\u3061\u3089\u304C\u5B8C\u4E86\u6B21\u7B2C\u3001\u30D5\u30A1\u30A4\u30EB\u89E3\u6790\u304C\u59CB\u307E\u308A\u307E\u3059\u3002 AddImageWizardAddingProgressVisual.subTitle1Label.text=\u30ED\u30FC\u30AB\u30EB\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u60C5\u5831\u3092\u8FFD\u52A0\u4E2D\u3067\u3059\u3002\u3053\u3061\u3089\u304C\u5B8C\u4E86\u6B21\u7B2C\u3001\u30D5\u30A1\u30A4\u30EB\u89E3\u6790\u304C\u59CB\u307E\u308A\u307E\u3059\u3002
ImageFilePanel.timeZoneLabel.text=\u30A4\u30F3\u30D7\u30C3\u30C8\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A ImageFilePanel.timeZoneLabel.text=\u30A4\u30F3\u30D7\u30C3\u30C8\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\uFF1A
ImageFilePanel.descLabel.text=\uFF08\u3088\u308A\u901F\u3044\u7D50\u679C\u3001\u3057\u304B\u3057\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u306F\u691C\u7D22\u3055\u308C\u307E\u305B\u3093\uFF09 ImageFilePanel.descLabel.text=\uFF08\u3088\u308A\u901F\u3044\u7D50\u679C\u3001\u3057\u304B\u3057\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u306F\u691C\u7D22\u3055\u308C\u307E\u305B\u3093\uFF09
@ -88,7 +88,7 @@ MissingImageDialog.browseButton.text=\u95B2\u89A7
AddImageWizardAddingProgressVisual.progressTextArea.border.title=\u30B9\u30C6\u30FC\u30BF\u30B9 AddImageWizardAddingProgressVisual.progressTextArea.border.title=\u30B9\u30C6\u30FC\u30BF\u30B9
AddImageAction.wizard.title=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0 AddImageAction.wizard.title=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0
AddImageAction.ingestConfig.ongoingIngest.msg=<html>\u4ED6\u306E\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u304C\u51E6\u7406\u4E2D\u3067\u3059\u3002\u65B0\u898F\u30BD\u30FC\u30B9\u3092\u4ECA\u8FFD\u52A0\u3059\u308B\u3068\u5B9F\u884C\u4E2D\u306E\u51E6\u7406\u304C\u9045\u304F\u306A\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002<br />\u3053\u306E\u307E\u307E\u5B9F\u884C\u3057\u3001\u65B0\u898F\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0\u3057\u307E\u3059\u304B\uFF1F</html> AddImageAction.ingestConfig.ongoingIngest.msg=<html>\u4ED6\u306E\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u304C\u51E6\u7406\u4E2D\u3067\u3059\u3002\u65B0\u898F\u30BD\u30FC\u30B9\u3092\u4ECA\u8FFD\u52A0\u3059\u308B\u3068\u5B9F\u884C\u4E2D\u306E\u51E6\u7406\u304C\u9045\u304F\u306A\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002<br />\u3053\u306E\u307E\u307E\u5B9F\u884C\u3057\u3001\u65B0\u898F\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u3092\u8FFD\u52A0\u3057\u307E\u3059\u304B\uFF1F</html>
AddImageAction.ingestConfig.ongoingIngest.title=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3092\u5B9F\u884C\u4E2D AddImageAction.ingestConfig.ongoingIngest.title=\u51E6\u7406\u4E2D
AddImageTask.run.progress.adding=\u8FFD\u52A0\u4E2D\uFF1A{0} AddImageTask.run.progress.adding=\u8FFD\u52A0\u4E2D\uFF1A{0}
AddImageTask.interrupt.exception.msg=\u30A4\u30E1\u30FC\u30B8\u8FFD\u52A0\u30D7\u30ED\u30BB\u30B9\u306E\u505C\u6B62\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 AddImageTask.interrupt.exception.msg=\u30A4\u30E1\u30FC\u30B8\u8FFD\u52A0\u30D7\u30ED\u30BB\u30B9\u306E\u505C\u6B62\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002
AddImageWizardAddingProgressPanel.isValid.focusNext=\u6B21 > AddImageWizardAddingProgressPanel.isValid.focusNext=\u6B21 >
@ -115,10 +115,12 @@ Case.open.msgDlg.updated.msg=\u30B1\u30FC\u30B9\u30C7\u30FC\u30BF\u30D9\u30FC\u3
Case.open.msgDlg.updated.title=\u30B1\u30FC\u30B9\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30B9\u30AD\u30FC\u30DE\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8 Case.open.msgDlg.updated.title=\u30B1\u30FC\u30B9\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u30B9\u30AD\u30FC\u30DE\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8
Case.open.exception.checkFile.msg=\u6B63\u3057\u3044\u30B1\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u3057\u305F\u304B\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\uFF08\u901A\u5E38\u62E1\u5F35\u5B50{0}\u3092\u6301\u3064\uFF09 Case.open.exception.checkFile.msg=\u6B63\u3057\u3044\u30B1\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E\u3057\u305F\u304B\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\uFF08\u901A\u5E38\u62E1\u5F35\u5B50{0}\u3092\u6301\u3064\uFF09
Case.open.exception.gen.msg=\u30B1\u30FC\u30B9\u3092\u958B\u304F\u306E\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F Case.open.exception.gen.msg=\u30B1\u30FC\u30B9\u3092\u958B\u304F\u306E\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F
Case.checkImgExist.confDlg.doesntExist.msg=\u4EE5\u524D\u3001\u30A4\u30E1\u30FC\u30B8\u306F\u4E0B\u8A18\u306B\u3042\u308A\u307E\u3057\u305F\uFF1A\ Case.checkImgExist.confDlg.doesntExist.msg={0} \u304C\u3053\u306E\u30B1\u30FC\u30B9\u306B\u95A2\u9023\u3059\u308B\u30A4\u30E1\u30FC\u30B8\u306E\uFF11\u500B\u304C\u6B20\u843D\u3057\u3066\u3044\u308B\u306E\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002\u305D\u308C\u3089\u3092\u4ECA\u304B\u3089\u691C\u7D22\u3057\u307E\u3059\u304B\uFF1F\
\
\u4EE5\u524D\u3001\u30A4\u30E1\u30FC\u30B8\u306F\u4E0B\u8A18\u306B\u3042\u308A\u307E\u3057\u305F\uFF1A\
{1}\ {1}\
\u4ECA\u5F8C\u3082\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u30D6\u30E9\u30A6\u30BA\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u304C\u3067\u304D\u307E\u3059 \u3044\u3044\u3048\u3092\u9078\u629E\u3057\u3066\u3082\u3001\u4ECA\u5F8C\u3082\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u95B2\u89A7\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u304C\u3067\u304D\u307E\u3059\u304C\u3001\u30D5\u30A1\u30A4\u30EB\u30B3\u30F3\u30C6\u30F3\u30C4\u306E\u8868\u793A\u307E\u305F\u306F\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30D7\u30ED\u30BB\u30B9\u306E\u5B9F\u884C\u304C\u3067\u304D\u306A\u304F\u306A\u308A\u307E\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.title=\u30A4\u30E1\u30FC\u30B8\u6B20\u843D Case.checkImgExist.confDlg.doesntExist.title=\u6B20\u843D\u30A4\u30E1\u30FC\u30B8
Case.addImg.exception.msg=\u30B1\u30FC\u30B9\u306B\u30A4\u30E1\u30FC\u30B8\u3092\u8FFD\u52A0\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F Case.addImg.exception.msg=\u30B1\u30FC\u30B9\u306B\u30A4\u30E1\u30FC\u30B8\u3092\u8FFD\u52A0\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F
Case.closeCase.exception.msg=\u73FE\u5728\u306E\u30B1\u30FC\u30B9\u3092\u9589\u3058\u308B\u6700\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002 Case.closeCase.exception.msg=\u73FE\u5728\u306E\u30B1\u30FC\u30B9\u3092\u9589\u3058\u308B\u6700\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002
Case.deleteCase.exception.msg=\u30B1\u30FC\u30B9\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u524A\u9664\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A{0} Case.deleteCase.exception.msg=\u30B1\u30FC\u30B9\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u524A\u9664\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A{0}
@ -165,8 +167,8 @@ LocalDiskDSProcessor.dsType.text=\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30B9\u30A
LocalDiskPanel.localDiskModel.loading.msg=\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30B9\u30AF\u3092\u30ED\u30FC\u30C9\u4E2D\u2026 LocalDiskPanel.localDiskModel.loading.msg=\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30B9\u30AF\u3092\u30ED\u30FC\u30C9\u4E2D\u2026
LocalDiskPanel.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC LocalDiskPanel.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC
LocalDiskPanel.moduleErr.msg=LocalDiskPanel\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 LocalDiskPanel.moduleErr.msg=LocalDiskPanel\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002
LocalDiskPanel.errLabel.disksNotDetected.text=\u30C7\u30A3\u30B9\u30AF\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4E00\u90E8\u306E\u30B7\u30B9\u30C6\u30E0\u3067\u306F\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\uFF08\u3082\u3057\u304F\u306F\u300C\u7BA1\u7406\u8005\u3068\u3057\u3066\u5B9F\u884C\u3059\u308B\u300D\uFF09\u3002 LocalDiskPanel.errLabel.disksNotDetected.text=\u30C7\u30A3\u30B9\u30AF\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4E00\u90E8\u306E\u30B7\u30B9\u30C6\u30E0\u3067\u306F\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\uFF08\u3082\u3057\u304F\u306F\u300C\u7BA1\u7406\u8005\u3068\u3057\u3066\u5B9F\u884C\u3059\u308B\u300D\u304C\u5FC5\u8981\uFF09\u3002
LocalDiskPanel.errLabel.disksNotDetected.toolTipText=\u30C7\u30A3\u30B9\u30AF\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4E00\u90E8\u306E\u30B7\u30B9\u30C6\u30E0\u3067\u306F\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\uFF08\u3082\u3057\u304F\u306F\u300C\u7BA1\u7406\u8005\u3068\u3057\u3066\u5B9F\u884C\u3059\u308B\u300D\uFF09\u3002 LocalDiskPanel.errLabel.disksNotDetected.toolTipText=\u30C7\u30A3\u30B9\u30AF\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4E00\u90E8\u306E\u30B7\u30B9\u30C6\u30E0\u3067\u306F\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\uFF08\u3082\u3057\u304F\u306F\u300C\u7BA1\u7406\u8005\u3068\u3057\u3066\u5B9F\u884C\u3059\u308B\u300D\u304C\u5FC5\u8981\uFF09\u3002
LocalDiskPanel.errLabel.drivesNotDetected.text=\u30ED\u30FC\u30AB\u30EB\u30C9\u30E9\u30A4\u30D6\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u81EA\u52D5\u691C\u51FA\u306F\u3053\u306EOS\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u304B\u3001\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\u3002 LocalDiskPanel.errLabel.drivesNotDetected.text=\u30ED\u30FC\u30AB\u30EB\u30C9\u30E9\u30A4\u30D6\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u81EA\u52D5\u691C\u51FA\u306F\u3053\u306EOS\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u304B\u3001\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\u3002
LocalDiskPanel.errLabel.drivesNotDetected.toolTipText=\u30ED\u30FC\u30AB\u30EB\u30C9\u30E9\u30A4\u30D6\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u81EA\u52D5\u691C\u51FA\u306F\u3053\u306EOS\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u304B\u3001\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\u3002 LocalDiskPanel.errLabel.drivesNotDetected.toolTipText=\u30ED\u30FC\u30AB\u30EB\u30C9\u30E9\u30A4\u30D6\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u81EA\u52D5\u691C\u51FA\u306F\u3053\u306EOS\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u304B\u3001\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\u3002
LocalDiskPanel.errLabel.someDisksNotDetected.text=\u4E00\u90E8\u306E\u30C7\u30A3\u30B9\u30AF\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4E00\u90E8\u306E\u30B7\u30B9\u30C6\u30E0\u3067\u306F\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\uFF08\u3082\u3057\u304F\u306F\u300C\u7BA1\u7406\u8005\u3068\u3057\u3066\u5B9F\u884C\u3059\u308B\u300D\uFF09\u3002 LocalDiskPanel.errLabel.someDisksNotDetected.text=\u4E00\u90E8\u306E\u30C7\u30A3\u30B9\u30AF\u304C\u691C\u51FA\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u4E00\u90E8\u306E\u30B7\u30B9\u30C6\u30E0\u3067\u306F\u7BA1\u7406\u8005\u6A29\u9650\u304C\u5FC5\u8981\u3067\u3059\uFF08\u3082\u3057\u304F\u306F\u300C\u7BA1\u7406\u8005\u3068\u3057\u3066\u5B9F\u884C\u3059\u308B\u300D\uFF09\u3002
@ -216,7 +218,7 @@ UpdateRecentCases.menuItem.empty=-\u7A7A\u767D-
XMLCaseManagement.create.exception.msg=\u30B1\u30FC\u30B9XML\u30D5\u30A1\u30A4\u30EB\u306E\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3001 XMLCaseManagement.create.exception.msg=\u30B1\u30FC\u30B9XML\u30D5\u30A1\u30A4\u30EB\u306E\u8A2D\u5B9A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3001
XMLCaseManagement.writeFile.exception.noCase.msg=\u30DE\u30CD\u30B8\u30E1\u30F3\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304F\u5FC5\u8981\u304C\u3042\u308B\u30B1\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002 XMLCaseManagement.writeFile.exception.noCase.msg=\u30DE\u30CD\u30B8\u30E1\u30F3\u30C8\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304F\u5FC5\u8981\u304C\u3042\u308B\u30B1\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002
XMLCaseManagement.writeFile.exception.errWriteToFile.msg=\u30B1\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F XMLCaseManagement.writeFile.exception.errWriteToFile.msg=\u30B1\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3078\u306E\u66F8\u304D\u8FBC\u307F\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F
XMLCaseManagement.open.exception.errReadXMLFile.msg=\u30B1\u30FC\u30B9XML\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u53D6\u308A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u3042\u308A\u307E\u3057\u305F\uFF1A{0} XMLCaseManagement.open.exception.errReadXMLFile.msg=\u30B1\u30FC\u30B9XML\u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u53D6\u308A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A{0}
XMLCaseManagement.open.msgDlg.notAutCase.msg=\u30A8\u30E9\u30FC\uFF1AAutopsy\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB("{0}")\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\ XMLCaseManagement.open.msgDlg.notAutCase.msg=\u30A8\u30E9\u30FC\uFF1AAutopsy\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB("{0}")\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002\
\ \
\u8A73\u7D30\uFF1A\ \u8A73\u7D30\uFF1A\
@ -224,3 +226,4 @@ Autopsy\u8A2D\u5B9A\u30D5\u30A1\u30A4\u30EB\u4EE5\u5916(at {1})\u306F\u958B\u305
XMLCaseManagement.open.msgDlg.notAutCase.title=\u30A8\u30E9\u30FC XMLCaseManagement.open.msgDlg.notAutCase.title=\u30A8\u30E9\u30FC
ImageFilePanel.noFatOrphansCheckbox.text=FAT\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u306E\u30AA\u30FC\u30D5\u30A1\u30F3\u30D5\u30A1\u30A4\u30EB\u306F\u7121\u8996 ImageFilePanel.noFatOrphansCheckbox.text=FAT\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u306E\u30AA\u30FC\u30D5\u30A1\u30F3\u30D5\u30A1\u30A4\u30EB\u306F\u7121\u8996
LocalDiskPanel.noFatOrphansCheckbox.text=FAT\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u306E\u30AA\u30FC\u30D5\u30A1\u30F3\u30D5\u30A1\u30A4\u30EB\u306F\u7121\u8996 LocalDiskPanel.noFatOrphansCheckbox.text=FAT\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u306E\u30AA\u30FC\u30D5\u30A1\u30F3\u30D5\u30A1\u30A4\u30EB\u306F\u7121\u8996
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=\u30AD\u30E3\u30F3\u30BB\u30EB

View File

@ -0,0 +1,16 @@
FileManager.findFiles.exception.msg=Attempted to use FileManager after it was closed.
FileManager.findFiles2.exception.msg=Attempted to use FileManager after it was closed.
FileManager.findFiles3.exception.msg=Attempted to use FileManager after it was closed.
FileManager.openFiles.exception.msg=Attempted to use FileManager after it was closed.
FileManager.addDerivedFile.exception.msg=Attempted to use FileManager after it was closed.
FileManager.addCarvedFile.exception.msg=Attempted to use FileManager after it was closed.
FileManager.addLocalFilesDirs.exception.notReadable.msg=One of the local files/dirs to add is not readable\: {0}, aborting the process before any files added
FileManager.addLocalFilesDirs.exception.cantAdd.msg=One of the local files/dirs could not be added\: {0}
FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=Error creating local file set dir\: {0}
FileManager.addLocalDirInt.exception.closed.msg=Attempted to use FileManager after it was closed.
FileManager.addLocalDirInt.exception.doesntExist.msg=Attempted to add a local dir that does not exist\: {0}
FileManager.addLocalDirInt.exception.notReadable.msg=Attempted to add a local dir that is not readable\: {0}
FileManager.addLocalDirInt2.exception.closed.msg=Attempted to use FileManager after it was closed.
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} out of content size range (0 - {1})
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1})
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset

View File

@ -0,0 +1,16 @@
FileManager.findFiles.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.findFiles2.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.findFiles3.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.openFiles.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addDerivedFile.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addCarvedFile.exception.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addLocalFilesDirs.exception.notReadable.msg=\u8FFD\u52A0\u3059\u308B\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u4E2D\u306B\u8AAD\u307F\u53D6\u308C\u306A\u3044\u3082\u306E\u304C\uFF11\u500B\u3042\u308A\u307E\u3059\uFF1A{0}\u3001\u30D5\u30A1\u30A4\u30EB\u304C\u8FFD\u52A0\u3055\u308C\u308B\u524D\u306B\u51E6\u7406\u3092\u4E2D\u6B62\u3057\u307E\u3059
FileManager.addLocalFilesDirs.exception.cantAdd.msg=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\uFF11\u500B\u306F\u8FFD\u52A0\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\uFF1A{0}
FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg=\u30ED\u30FC\u30AB\u30EB\u30D5\u30A1\u30A4\u30EB\u30BB\u30C3\u30C8\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u4F5C\u6210\u306B\u30A8\u30E9\u30FC\u304C\u8D77\u3053\u308A\u307E\u3057\u305F\uFF1A {0}
FileManager.addLocalDirInt.exception.closed.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
FileManager.addLocalDirInt.exception.doesntExist.msg=\u5B58\u5728\u3057\u306A\u3044\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u8FFD\u52A0\u3092\u8A66\u307F\u307E\u3057\u305F\: {0}
FileManager.addLocalDirInt.exception.notReadable.msg=\u8AAD\u307F\u53D6\u308A\u3067\u304D\u306A\u3044\u30ED\u30FC\u30AB\u30EB\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u8FFD\u52A0\u3092\u8A66\u307F\u307E\u3057\u305F\: {0}
FileManager.addLocalDirInt2.exception.closed.msg=FileManager\u3092\u9589\u3058\u305F\u5F8C\u306B\u4F7F\u7528\u3092\u8A66\u307F\u307E\u3057\u305F\u3002
TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0} \u30B3\u30F3\u30C6\u30F3\u30C4\u30B5\u30A4\u30BA\u7BC4\u56F2(0 - {1})\u306E\u5916\u3067\u3059
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} \u30B3\u30F3\u30C6\u30F3\u30C4\u30B5\u30A4\u30BA\u7BC4\u56F2(0 - {1})\u306E\u5916\u3067\u3059
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset

View File

@ -27,6 +27,8 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
@ -90,7 +92,7 @@ public class FileManager implements Closeable {
*/ */
public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName) throws TskCoreException { public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg"));
} }
return tskCase.findFiles(dataSource, fileName); return tskCase.findFiles(dataSource, fileName);
} }
@ -111,7 +113,7 @@ public class FileManager implements Closeable {
*/ */
public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, String dirName) throws TskCoreException { public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, String dirName) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg"));
} }
return tskCase.findFiles(dataSource, fileName, dirName); return tskCase.findFiles(dataSource, fileName, dirName);
} }
@ -131,7 +133,7 @@ public class FileManager implements Closeable {
*/ */
public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException { public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg"));
} }
return findFiles(dataSource, fileName, parentFile.getName()); return findFiles(dataSource, fileName, parentFile.getName());
} }
@ -146,7 +148,7 @@ public class FileManager implements Closeable {
*/ */
public synchronized List<AbstractFile> openFiles(Content dataSource, String filePath) throws TskCoreException { public synchronized List<AbstractFile> openFiles(Content dataSource, String filePath) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.openFiles.exception.msg"));
} }
return tskCase.openFiles(dataSource, filePath); return tskCase.openFiles(dataSource, filePath);
} }
@ -187,7 +189,7 @@ public class FileManager implements Closeable {
String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException { String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addDerivedFile.exception.msg"));
} }
return tskCase.addDerivedFile(fileName, localPath, size, return tskCase.addDerivedFile(fileName, localPath, size,
@ -213,7 +215,7 @@ public class FileManager implements Closeable {
long systemId, List<TskFileRange> sectors) throws TskCoreException { long systemId, List<TskFileRange> sectors) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg"));
} }
return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, sectors); return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, sectors);
@ -256,7 +258,9 @@ public class FileManager implements Closeable {
for (String absPath : localAbsPaths) { for (String absPath : localAbsPaths) {
java.io.File localFile = new java.io.File(absPath); java.io.File localFile = new java.io.File(absPath);
if (!localFile.exists() || !localFile.canRead()) { if (!localFile.exists() || !localFile.canRead()) {
String msg = "One of the local files/dirs to add is not readable: " + localFile.getAbsolutePath() + ", aborting the process before any files added"; String msg = NbBundle
.getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.notReadable.msg",
localFile.getAbsolutePath());
logger.log(Level.SEVERE, msg); logger.log(Level.SEVERE, msg);
throw new TskCoreException(msg); throw new TskCoreException(msg);
} }
@ -273,7 +277,9 @@ public class FileManager implements Closeable {
AbstractFile localFileAdded = addLocalDirInt(trans, fileSetRootDir, localRootToAdd, addProgressUpdater); AbstractFile localFileAdded = addLocalDirInt(trans, fileSetRootDir, localRootToAdd, addProgressUpdater);
if (localFileAdded == null) { if (localFileAdded == null) {
String msg = "One of the local files/dirs could not be added: " + localRootToAdd.getAbsolutePath(); String msg = NbBundle
.getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.cantAdd.msg",
localRootToAdd.getAbsolutePath());
logger.log(Level.SEVERE, msg); logger.log(Level.SEVERE, msg);
throw new TskCoreException(msg); throw new TskCoreException(msg);
} else { } else {
@ -282,7 +288,7 @@ public class FileManager implements Closeable {
//for now reusing ingest events, in future this will be replaced by datamodel / observer sending out events //for now reusing ingest events, in future this will be replaced by datamodel / observer sending out events
// @@@ Is this the right place for this? A directory tree refresh will be triggered, so this may be creating a race condition // @@@ Is this the right place for this? A directory tree refresh will be triggered, so this may be creating a race condition
// since the transaction is not yet committed. // since the transaction is not yet committed.
IngestServices.getDefault().fireModuleContentEvent(new ModuleContentEvent(localFileAdded)); IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(localFileAdded));
} }
} }
@ -314,7 +320,9 @@ public class FileManager implements Closeable {
created = tskCase.addVirtualDirectory(0, fileSetName, trans); created = tskCase.addVirtualDirectory(0, fileSetName, trans);
curNumFileSets = newFileSetCount; curNumFileSets = newFileSetCount;
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
String msg = "Error creating local file set dir: " + fileSetName; String msg = NbBundle
.getMessage(this.getClass(), "FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg",
fileSetName);
logger.log(Level.SEVERE, msg, ex); logger.log(Level.SEVERE, msg, ex);
throw new TskCoreException(msg, ex); throw new TskCoreException(msg, ex);
} }
@ -339,15 +347,20 @@ public class FileManager implements Closeable {
java.io.File localFile, FileAddProgressUpdater addProgressUpdater) throws TskCoreException { java.io.File localFile, FileAddProgressUpdater addProgressUpdater) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.closed.msg"));
} }
//final String localName = localDir.getName(); //final String localName = localDir.getName();
if (!localFile.exists()) { if (!localFile.exists()) {
throw new TskCoreException("Attempted to add a local dir that does not exist: " + localFile.getAbsolutePath()); throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.doesntExist.msg",
localFile.getAbsolutePath()));
} }
if (!localFile.canRead()) { if (!localFile.canRead()) {
throw new TskCoreException("Attempted to add a local dir that is not readable: " + localFile.getAbsolutePath()); throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.notReadable.msg",
localFile.getAbsolutePath()));
} }
@ -389,7 +402,8 @@ public class FileManager implements Closeable {
private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, Transaction trans) throws TskCoreException { private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, Transaction trans) throws TskCoreException {
if (tskCase == null) { if (tskCase == null) {
throw new TskCoreException("Attempted to use FileManager after it was closed."); throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt2.exception.closed.msg"));
} }
long size = localFile.length(); long size = localFile.length();

View File

@ -25,6 +25,8 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardArtifactTag;
@ -198,15 +200,20 @@ public class TagsManager implements Closeable {
if (beginByteOffset >= 0 && endByteOffset >= 1) { if (beginByteOffset >= 0 && endByteOffset >= 1) {
if (beginByteOffset > content.getSize() - 1) { if (beginByteOffset > content.getSize() - 1) {
throw new IllegalArgumentException("beginByteOffset = " + beginByteOffset + " out of content size range (0 - " + (content.getSize() - 1) + ")"); throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
"TagsManager.addContentTag.exception.beginByteOffsetOOR.msg",
beginByteOffset, content.getSize() - 1));
} }
if (endByteOffset > content.getSize() - 1) { if (endByteOffset > content.getSize() - 1) {
throw new IllegalArgumentException("endByteOffset = " + endByteOffset + " out of content size range (0 - " + (content.getSize() - 1) + ")"); throw new IllegalArgumentException(
NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endByteOffsetOOR.msg",
endByteOffset, content.getSize() - 1));
} }
if (endByteOffset < beginByteOffset) { if (endByteOffset < beginByteOffset) {
throw new IllegalArgumentException("endByteOffset < beginByteOffset"); throw new IllegalArgumentException(
NbBundle.getMessage(this.getClass(), "TagsManager.addContentTag.exception.endLTbegin.msg"));
} }
} }

View File

@ -1,8 +1,8 @@
OpenIDE-Module-Display-Category=\u57FA\u76E4 OpenIDE-Module-Display-Category=\u57FA\u76E4
OpenIDE-Module-Long-Description=\ OpenIDE-Module-Long-Description=\
Autopsy\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30B3\u30A2\u3067\u3059\u3002\n\n\ Autopsy\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30B3\u30A2\u3067\u3059\u3002\n\n\
\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u307F\u3067\u5B9F\u884C\u3059\u308B\u306E\u306B\u5FC5\u8981\u306A\u4E3B\u8981\u306A\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF1ARCP\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3001\u30A6\u30A3\u30F3\u30C9\u30A6\u30A4\u30F3\u30B0GUI\u3001Sleuth Kit\u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0\u3001\u30C7\u30FC\u30BF\u30E2\u30C7\u30EB\uFF0F\u30B9\u30C8\u30EC\u30FC\u30B8\u3001\u30A8\u30AF\u30B9\u30D7\u30ED\u30FC\u30E9\u3001\u7D50\u679C\u30D3\u30E5\u30FC\u30A2\u30FC\u3001\u30B3\u30F3\u30C6\u30F3\u30C4\u30D3\u30E5\u30FC\u30A2\u30FC\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u7528\u30D5\u30EC\u30FC\u30E0\u30EF\u30FC\u30AF\u3001\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u3001\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u7B49\u306E\u4E3B\u8981\u30C4\u30FC\u30EB\u3002\n\n\ \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\u307F\u3067\u5B9F\u884C\u3059\u308B\u306E\u306B\u5FC5\u8981\u306A\u4E3B\u8981\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u304C\u542B\u307E\u308C\u3066\u3044\u307E\u3059\uFF1ARCP\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3001\u30A6\u30A3\u30F3\u30C9\u30A6\u30A4\u30F3\u30B0GUI\u3001Sleuth Kit\u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0\u3001\u30C7\u30FC\u30BF\u30E2\u30C7\u30EB\uFF0F\u30B9\u30C8\u30EC\u30FC\u30B8\u3001\u30A8\u30AF\u30B9\u30D7\u30ED\u30FC\u30E9\u3001\u7D50\u679C\u30D3\u30E5\u30FC\u30A2\u3001\u30B3\u30F3\u30C6\u30F3\u30C4\u30D3\u30E5\u30FC\u30A2\u3001\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u7528\u30D5\u30EC\u30FC\u30E0\u30EF\u30FC\u30AF\u3001\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u3001\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u7B49\u306E\u4E3B\u8981\u30C4\u30FC\u30EB\u3002\n\n\
\u30E2\u30B8\u30E5\u30FC\u30EB\u5185\u306E\u30D5\u30EC\u30FC\u30E0\u30EF\u30FC\u30AF\u306B\u306F\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3001\u30D3\u30E5\u30FC\u30A2\u30FC\u3001\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u958B\u767A\u7528\u306EAPI\u304C\u542B\u307E\u308C\u307E\u3059\u3002\ \u30E2\u30B8\u30E5\u30FC\u30EB\u5185\u306E\u30D5\u30EC\u30FC\u30E0\u30EF\u30FC\u30AF\u306B\u306F\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u3001\u30D3\u30E5\u30FC\u30A2\u3001\u30EC\u30DD\u30FC\u30C8\u751F\u6210\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u958B\u767A\u7528\u306EAPI\u304C\u542B\u307E\u308C\u307E\u3059\u3002\
\u30E2\u30B8\u30E5\u30FC\u30EB\u306FAutopsy\u30D7\u30E9\u30B0\u30A4\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FC\u3092\u4F7F\u7528\u3057\u3001\u30D7\u30E9\u30B0\u30A4\u30F3\u3068\u3057\u3066\u5B9F\u88C5\u3067\u304D\u307E\u3059\u3002\n\ \u30E2\u30B8\u30E5\u30FC\u30EB\u306FAutopsy\u30D7\u30E9\u30B0\u30A4\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30E9\u30FC\u3092\u4F7F\u7528\u3057\u3001\u30D7\u30E9\u30B0\u30A4\u30F3\u3068\u3057\u3066\u5B9F\u88C5\u3067\u304D\u307E\u3059\u3002\n\
\u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u3066\u3044\u306A\u3051\u308C\u3070\u3001Autopsy\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\n\n\ \u3053\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u306F\u30A2\u30F3\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3057\u3066\u306F\u3044\u3051\u307E\u305B\u3093\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u3066\u3044\u306A\u3051\u308C\u3070\u3001Autopsy\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\n\n\
\u8A73\u7D30\u306F\u4E0B\u8A18\u3092\u3054\u89A7\u4E0B\u3055\u3044\u3002http\://www.sleuthkit.org/autopsy/ \u8A73\u7D30\u306F\u4E0B\u8A18\u3092\u3054\u89A7\u4E0B\u3055\u3044\u3002http\://www.sleuthkit.org/autopsy/

View File

@ -122,8 +122,13 @@
</folder> </folder>
<folder name="Help"> <folder name="Help">
<file name="org-netbeans-core-actions-AboutAction.instance_hidden"/> <file name="org-netbeans-core-actions-AboutAction.instance_hidden"/>
<file name="org-sleuthkit-autopsy-corecomponents-CustomAboutAction.instance"> <file name="org-sleuthkit-autopsy-actions-OpenLogFolder.instance_hidden"/>
<attr name="delegate" newvalue="org.sleuthkit.autopsy.corecomponents.CustomAboutAction"/> <file name="org-sleuthkit-autopsy-actions-OpenLogFolderAction.instance">
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/>
</file>
<file name="org-sleuthkit-autopsy-corecomponents-AboutWindowAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.corecomponents.AboutWindowAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.corecomponents.Bundle#CTL_CustomAboutAction"/> <attr name="displayName" bundlevalue="org.sleuthkit.autopsy.corecomponents.Bundle#CTL_CustomAboutAction"/>
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/> <attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
<attr name="noIconInMenu" boolvalue="false"/> <attr name="noIconInMenu" boolvalue="false"/>
@ -152,8 +157,9 @@
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/> <attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/>
<attr name="position" intvalue="101"/> <attr name="position" intvalue="101"/>
</file> </file>
<folder name="Open Recent Case"> <folder name="OpenRecentCase">
<attr name="position" intvalue="102"/> <attr name="position" intvalue="102"/>
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.sleuthkit.autopsy.casemodule.Bundle"/>
<file name="org-sleuthkit-autopsy-casemodule-RecentCasesAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-RecentCasesAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/> <attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/>
</file> </file>
@ -259,7 +265,7 @@
<file name="org-netbeans-modules-autoupdate-ui-actions-CheckForUpdatesAction.shadow_hidden"/> <file name="org-netbeans-modules-autoupdate-ui-actions-CheckForUpdatesAction.shadow_hidden"/>
<attr name="master-help.xml/org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow" boolvalue="true"/> <attr name="master-help.xml/org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow" boolvalue="true"/>
<file name="org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow"> <file name="org-sleuthkit-autopsy-corecomponents-CustomAboutAction.shadow">
<attr name="originalFile" stringvalue="Actions/Help/org-sleuthkit-autopsy-corecomponents-CustomAboutAction.instance"/> <attr name="originalFile" stringvalue="Actions/Help/org-sleuthkit-autopsy-corecomponents-AboutWindowAction.instance"/>
<attr name="position" intvalue="3000"/> <attr name="position" intvalue="3000"/>
</file> </file>
</folder> </folder>
@ -316,6 +322,12 @@
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.FileReportText.getDefault"/> <attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.FileReportText.getDefault"/>
<attr name="position" intvalue="903"/> <attr name="position" intvalue="903"/>
</file> </file>
<file name="org-sleuthkit-autopsy-report-ReportKML.instance">
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.report.GeneralReportModule"/>
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.ReportKML.getDefault"/>
<attr name="position" intvalue="904"/>
</file>
<!--<folder name="JavaHelp"> <!--<folder name="JavaHelp">
<file name="casemodule-helpset.xml" url="casemodule-helpset.xml"> <file name="casemodule-helpset.xml" url="casemodule-helpset.xml">
<attr name="position" intvalue="3075"/> <attr name="position" intvalue="3075"/>

View File

@ -28,16 +28,16 @@ import org.sleuthkit.autopsy.coreutils.Logger;
/** /**
* Action to open custom implementation of the "About" window from the Help menu. * Action to open custom implementation of the "About" window from the Help menu.
*/ */
class CustomAboutAction extends AboutAction { class AboutWindowAction extends AboutAction {
@Override @Override
public void performAction() { public void performAction() {
Logger.noteAction(this.getClass()); Logger.noteAction(this.getClass());
ProductInformationPanel pip = new ProductInformationPanel(); AboutWindowPanel pip = new AboutWindowPanel();
DialogDescriptor descriptor = new DialogDescriptor( DialogDescriptor descriptor = new DialogDescriptor(
pip, pip,
NbBundle.getMessage(CustomAboutAction.class, "CTL_CustomAboutAction"), NbBundle.getMessage(AboutWindowAction.class, "CTL_CustomAboutAction"),
true, true,
new Object[0], new Object[0],
null, null,

View File

@ -35,7 +35,6 @@ import org.netbeans.core.actions.HTMLViewAction;
import org.openide.awt.HtmlBrowser; import org.openide.awt.HtmlBrowser;
import org.openide.modules.Places; import org.openide.modules.Places;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.datamodel.SleuthkitJNI; import org.sleuthkit.datamodel.SleuthkitJNI;
@ -43,17 +42,17 @@ import org.sleuthkit.datamodel.SleuthkitJNI;
/** /**
* Custom "About" window panel. * Custom "About" window panel.
*/ */
public class ProductInformationPanel extends JPanel implements HyperlinkListener { public class AboutWindowPanel extends JPanel implements HyperlinkListener {
private URL url = null; private URL url = null;
private Icon about; private Icon about;
private boolean verboseLogging; private boolean verboseLogging;
public ProductInformationPanel() { public AboutWindowPanel() {
about = new ImageIcon(org.netbeans.core.startup.Splash.loadContent(true)); about = new ImageIcon(org.netbeans.core.startup.Splash.loadContent(true));
initComponents(); initComponents();
jLabel1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); jLabel1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
description.setText(org.openide.util.NbBundle.getMessage(ProductInformationPanel.class, description.setText(org.openide.util.NbBundle.getMessage(AboutWindowPanel.class,
"LBL_Description", new Object[]{getProductVersionValue(), getJavaValue(), getVMValue(), "LBL_Description", new Object[]{getProductVersionValue(), getJavaValue(), getVMValue(),
getOperatingSystemValue(), getEncodingValue(), getSystemLocaleValue(), getUserDirValue(), getSleuthKitVersionValue(), Version.getNetbeansBuild(), Version.getBuildType().toString()})); getOperatingSystemValue(), getEncodingValue(), getSystemLocaleValue(), getUserDirValue(), getSleuthKitVersionValue(), Version.getNetbeansBuild(), Version.getBuildType().toString()}));
description.addHyperlinkListener(this); description.addHyperlinkListener(this);
@ -96,7 +95,7 @@ public class ProductInformationPanel extends JPanel implements HyperlinkListener
copyright.setBorder(null); copyright.setBorder(null);
copyright.setContentType("text/html"); // NOI18N copyright.setContentType("text/html"); // NOI18N
copyright.setEditable(false); copyright.setEditable(false);
copyright.setText(org.openide.util.NbBundle.getBundle(ProductInformationPanel.class).getString("LBL_Copyright")); // NOI18N copyright.setText(org.openide.util.NbBundle.getBundle(AboutWindowPanel.class).getString("LBL_Copyright")); // NOI18N
copyright.addMouseListener(new java.awt.event.MouseAdapter() { copyright.addMouseListener(new java.awt.event.MouseAdapter() {
public void mouseClicked(java.awt.event.MouseEvent evt) { public void mouseClicked(java.awt.event.MouseEvent evt) {
copyrightMouseClicked(evt); copyrightMouseClicked(evt);
@ -109,8 +108,7 @@ public class ProductInformationPanel extends JPanel implements HyperlinkListener
jScrollPane2.setViewportView(description); jScrollPane2.setViewportView(description);
verboseLoggingButton.setBackground(new java.awt.Color(255, 255, 255)); verboseLoggingButton.setBackground(new java.awt.Color(255, 255, 255));
verboseLoggingButton.setText( verboseLoggingButton.setText("Activate verbose logging");
NbBundle.getMessage(this.getClass(), "ProductInformationPanel.actVerboseLogging.text"));
verboseLoggingButton.addActionListener(new java.awt.event.ActionListener() { verboseLoggingButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
activateVerboseLogging(evt); activateVerboseLogging(evt);
@ -118,7 +116,7 @@ public class ProductInformationPanel extends JPanel implements HyperlinkListener
}); });
jButton2.setBackground(new java.awt.Color(255, 255, 255)); jButton2.setBackground(new java.awt.Color(255, 255, 255));
jButton2.setText(NbBundle.getMessage(ProductInformationPanel.class, "LBL_Close")); // NOI18N jButton2.setText(NbBundle.getMessage(AboutWindowPanel.class, "LBL_Close")); // NOI18N
jButton2.addActionListener(new java.awt.event.ActionListener() { jButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton2ActionPerformed(evt); jButton2ActionPerformed(evt);
@ -172,7 +170,7 @@ private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRS
private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabel1MouseClicked private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jLabel1MouseClicked
try { try {
url = new URL(NbBundle.getMessage(ProductInformationPanel.class, "URL_ON_IMG")); // NOI18N url = new URL(NbBundle.getMessage(AboutWindowPanel.class, "URL_ON_IMG")); // NOI18N
showUrl(); showUrl();
} catch (MalformedURLException ex) { } catch (MalformedURLException ex) {
//ignore //ignore
@ -226,29 +224,29 @@ private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:eve
} }
private static String getOperatingSystemValue() { private static String getOperatingSystemValue() {
return NbBundle.getMessage(ProductInformationPanel.class, "Format_OperatingSystem_Value", return NbBundle.getMessage(AboutWindowPanel.class, "Format_OperatingSystem_Value",
System.getProperty("os.name", System.getProperty("os.name",
NbBundle.getMessage(ProductInformationPanel.class, NbBundle.getMessage(AboutWindowPanel.class,
"ProductInformationPanel.propertyUnknown.text")), "ProductInformationPanel.propertyUnknown.text")),
System.getProperty("os.version", System.getProperty("os.version",
NbBundle.getMessage(ProductInformationPanel.class, NbBundle.getMessage(AboutWindowPanel.class,
"ProductInformationPanel.propertyUnknown.text")), "ProductInformationPanel.propertyUnknown.text")),
System.getProperty("os.arch", System.getProperty("os.arch",
NbBundle.getMessage(ProductInformationPanel.class, NbBundle.getMessage(AboutWindowPanel.class,
"ProductInformationPanel.propertyUnknown.text"))); "ProductInformationPanel.propertyUnknown.text")));
} }
private static String getJavaValue() { private static String getJavaValue() {
return System.getProperty("java.version", return System.getProperty("java.version",
NbBundle.getMessage(ProductInformationPanel.class, NbBundle.getMessage(AboutWindowPanel.class,
"ProductInformationPanel.propertyUnknown.text")); "ProductInformationPanel.propertyUnknown.text"));
} }
private static String getVMValue() { private static String getVMValue() {
return NbBundle.getMessage(ProductInformationPanel.class, return NbBundle.getMessage(AboutWindowPanel.class,
"ProductInformationPanel.getVMValue.text", "ProductInformationPanel.getVMValue.text",
System.getProperty("java.vm.name", System.getProperty("java.vm.name",
NbBundle.getMessage(ProductInformationPanel.class, NbBundle.getMessage(AboutWindowPanel.class,
"ProductInformationPanel.propertyUnknown.text")), "ProductInformationPanel.propertyUnknown.text")),
System.getProperty("java.vm.version", "")); System.getProperty("java.vm.version", ""));
} }
@ -264,7 +262,7 @@ private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:eve
private static String getEncodingValue() { private static String getEncodingValue() {
return System.getProperty("file.encoding", return System.getProperty("file.encoding",
NbBundle.getMessage(ProductInformationPanel.class, "ProductInformationPanel.propertyUnknown.text")); NbBundle.getMessage(AboutWindowPanel.class, "ProductInformationPanel.propertyUnknown.text"));
} }
public void setCopyright(String text) { public void setCopyright(String text) {

View File

@ -1,8 +1,8 @@
CTL_DataContentAction=DataContent CTL_DataContentAction=DataContent
CTL_DataContentTopComponent=Data Content CTL_DataContentTopComponent=Data Content
CTL_CustomAboutAction=About CTL_CustomAboutAction=About
OptionsCategory_Name_General=Display OptionsCategory_Name_General=Autopsy
OptionsCategory_Keywords_General=display OptionsCategory_Keywords_General=Autopsy Options
HINT_DataContentTopComponent=This is a DataContent window HINT_DataContentTopComponent=This is a DataContent window
HINT_NodeTableTopComponent=This is a DataResult window HINT_NodeTableTopComponent=This is a DataResult window
OpenIDE-Module-Name=CoreComponents OpenIDE-Module-Name=CoreComponents
@ -147,3 +147,4 @@ DataResultViewerThumbnail.switchPage.done.errMsg=Error making thumbnails\: {0}
FXVideoPanel.pauseButton.infoLabel.playbackErr=Playback error. FXVideoPanel.pauseButton.infoLabel.playbackErr=Playback error.
GstVideoPanel.progress.infoLabel.updateErr=Error updating video progress\: {0} GstVideoPanel.progress.infoLabel.updateErr=Error updating video progress\: {0}
GstVideoPanel.ExtractMedia.progress.buffering=Buffering {0} GstVideoPanel.ExtractMedia.progress.buffering=Buffering {0}
GeneralPanel.jLabel4.text=Number of threads to use for file ingest:

View File

@ -24,7 +24,7 @@ import java.util.List;
/** /**
* Interface used to capture frames from a video file. * Interface used to capture frames from a video file.
*/ */
interface FrameCapture { public interface FrameCapture {
/** /**
* @param file the video file to use * @param file the video file to use

View File

@ -30,7 +30,7 @@ import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_General", @OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_General",
iconBase = "org/sleuthkit/autopsy/corecomponents/display-options.png", iconBase = "org/sleuthkit/autopsy/corecomponents/checkbox.png",
position = 1, position = 1,
keywords = "#OptionsCategory_Keywords_General", keywords = "#OptionsCategory_Keywords_General",
keywordsCategory = "General") keywordsCategory = "General")

View File

@ -42,6 +42,7 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jLabel1" min="-2" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="jLabel3" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="jLabel4" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/> <EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
@ -49,10 +50,11 @@
<Component id="useBestViewerRB" min="-2" max="-2" attributes="0"/> <Component id="useBestViewerRB" min="-2" max="-2" attributes="0"/>
<Component id="dataSourcesHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="dataSourcesHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="viewsHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="viewsHideKnownCB" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="numberOfFileIngestThreadsComboBox" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
<EmptySpace min="0" pref="13" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</Group> </Group>
@ -78,7 +80,10 @@
<Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/> <Component id="useLocalTimeRB" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="useGMTTimeRB" min="-2" max="-2" attributes="0"/> <Component id="useGMTTimeRB" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="30" max="32767" attributes="0"/> <EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jLabel4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="numberOfFileIngestThreadsComboBox" min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -173,5 +178,25 @@
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="jLabel4">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="GeneralPanel.jLabel4.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JComboBox" name="numberOfFileIngestThreadsComboBox">
<Properties>
<Property name="model" type="javax.swing.ComboBoxModel" editor="org.netbeans.modules.form.editors2.ComboBoxModelEditor">
<StringArray count="4">
<StringItem index="0" value="1"/>
<StringItem index="1" value="2"/>
<StringItem index="2" value="3"/>
<StringItem index="3" value="4"/>
</StringArray>
</Property>
<Property name="selectedIndex" type="int" value="1"/>
</Properties>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2013-2014 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -21,10 +21,10 @@ package org.sleuthkit.autopsy.corecomponents;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import org.openide.util.NbPreferences; import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.IngestManager;
final class GeneralPanel extends javax.swing.JPanel { final class GeneralPanel extends javax.swing.JPanel {
private final GeneralOptionsPanelController controller;
private static final String KEEP_PREFERRED_VIEWER = "keepPreferredViewer"; private static final String KEEP_PREFERRED_VIEWER = "keepPreferredViewer";
private static final String USE_LOCAL_TIME = "useLocalTime"; private static final String USE_LOCAL_TIME = "useLocalTime";
private static final String DS_HIDE_KNOWN = "dataSourcesHideKnown"; // Default false private static final String DS_HIDE_KNOWN = "dataSourcesHideKnown"; // Default false
@ -32,7 +32,6 @@ final class GeneralPanel extends javax.swing.JPanel {
private final Preferences prefs = NbPreferences.forModule(this.getClass()); private final Preferences prefs = NbPreferences.forModule(this.getClass());
GeneralPanel(GeneralOptionsPanelController controller) { GeneralPanel(GeneralOptionsPanelController controller) {
this.controller = controller;
initComponents(); initComponents();
ContentUtils.setDisplayInLocalTime(useLocalTimeRB.isSelected()); ContentUtils.setDisplayInLocalTime(useLocalTimeRB.isSelected());
// TODO listen to changes in form fields and call controller.changed() // TODO listen to changes in form fields and call controller.changed()
@ -57,6 +56,8 @@ final class GeneralPanel extends javax.swing.JPanel {
jLabel3 = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel();
dataSourcesHideKnownCB = new javax.swing.JCheckBox(); dataSourcesHideKnownCB = new javax.swing.JCheckBox();
viewsHideKnownCB = new javax.swing.JCheckBox(); viewsHideKnownCB = new javax.swing.JCheckBox();
jLabel4 = new javax.swing.JLabel();
numberOfFileIngestThreadsComboBox = new javax.swing.JComboBox();
buttonGroup1.add(useBestViewerRB); buttonGroup1.add(useBestViewerRB);
useBestViewerRB.setSelected(true); useBestViewerRB.setSelected(true);
@ -94,6 +95,11 @@ final class GeneralPanel extends javax.swing.JPanel {
org.openide.awt.Mnemonics.setLocalizedText(viewsHideKnownCB, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.viewsHideKnownCB.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(viewsHideKnownCB, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.viewsHideKnownCB.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(GeneralPanel.class, "GeneralPanel.jLabel4.text")); // NOI18N
numberOfFileIngestThreadsComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "1", "2", "3", "4" }));
numberOfFileIngestThreadsComboBox.setSelectedIndex(1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -114,14 +120,16 @@ final class GeneralPanel extends javax.swing.JPanel {
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel1) .addComponent(jLabel1)
.addComponent(jLabel3) .addComponent(jLabel3)
.addComponent(jLabel4)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10) .addGap(10, 10, 10)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(keepCurrentViewerRB) .addComponent(keepCurrentViewerRB)
.addComponent(useBestViewerRB) .addComponent(useBestViewerRB)
.addComponent(dataSourcesHideKnownCB) .addComponent(dataSourcesHideKnownCB)
.addComponent(viewsHideKnownCB)))) .addComponent(viewsHideKnownCB)
.addGap(0, 13, Short.MAX_VALUE)))) .addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addGap(0, 0, Short.MAX_VALUE))))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -143,7 +151,10 @@ final class GeneralPanel extends javax.swing.JPanel {
.addComponent(useLocalTimeRB) .addComponent(useLocalTimeRB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(useGMTTimeRB) .addComponent(useGMTTimeRB)
.addContainerGap(30, Short.MAX_VALUE)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -164,6 +175,7 @@ final class GeneralPanel extends javax.swing.JPanel {
useGMTTimeRB.setSelected(!useLocalTime); useGMTTimeRB.setSelected(!useLocalTime);
dataSourcesHideKnownCB.setSelected(prefs.getBoolean(DS_HIDE_KNOWN, false)); dataSourcesHideKnownCB.setSelected(prefs.getBoolean(DS_HIDE_KNOWN, false));
viewsHideKnownCB.setSelected(prefs.getBoolean(VIEWS_HIDE_KNOWN, true)); viewsHideKnownCB.setSelected(prefs.getBoolean(VIEWS_HIDE_KNOWN, true));
numberOfFileIngestThreadsComboBox.setSelectedItem(IngestManager.getInstance().getNumberOfFileIngestThreads());
} }
void store() { void store() {
@ -171,6 +183,7 @@ final class GeneralPanel extends javax.swing.JPanel {
prefs.putBoolean(USE_LOCAL_TIME, useLocalTimeRB.isSelected()); prefs.putBoolean(USE_LOCAL_TIME, useLocalTimeRB.isSelected());
prefs.putBoolean(DS_HIDE_KNOWN, dataSourcesHideKnownCB.isSelected()); prefs.putBoolean(DS_HIDE_KNOWN, dataSourcesHideKnownCB.isSelected());
prefs.putBoolean(VIEWS_HIDE_KNOWN, viewsHideKnownCB.isSelected()); prefs.putBoolean(VIEWS_HIDE_KNOWN, viewsHideKnownCB.isSelected());
IngestManager.getInstance().setNumberOfFileIngestThreads(Integer.valueOf(numberOfFileIngestThreadsComboBox.getSelectedItem().toString()));
} }
boolean valid() { boolean valid() {
@ -184,7 +197,9 @@ final class GeneralPanel extends javax.swing.JPanel {
private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JRadioButton keepCurrentViewerRB; private javax.swing.JRadioButton keepCurrentViewerRB;
private javax.swing.JComboBox numberOfFileIngestThreadsComboBox;
private javax.swing.JRadioButton useBestViewerRB; private javax.swing.JRadioButton useBestViewerRB;
private javax.swing.JRadioButton useGMTTimeRB; private javax.swing.JRadioButton useGMTTimeRB;
private javax.swing.JRadioButton useLocalTimeRB; private javax.swing.JRadioButton useLocalTimeRB;

View File

@ -5,7 +5,7 @@ import java.awt.Image;
/** /**
* *
*/ */
class VideoFrame { public class VideoFrame {
private Image frame; private Image frame;
private long timeMillis; private long timeMillis;

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -90,7 +90,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
outputStringRedirect = null; outputStringRedirect = null;
//gc process with its streams //gc process with its streams
proc = null; //proc = null;
return output; return output;
} }
@ -137,7 +137,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
logger.log(Level.INFO, aCommand + " exit value: " + exitVal); logger.log(Level.INFO, aCommand + " exit value: " + exitVal);
//gc process with its streams //gc process with its streams
proc = null; //proc = null;
} }
/** /**

View File

@ -208,11 +208,11 @@ public class PlatformUtil {
* @throws IOException exception thrown if extract the file failed for IO * @throws IOException exception thrown if extract the file failed for IO
* reasons * reasons
*/ */
public static <T> boolean extractResourceToUserConfigDir(final Class<T> resourceClass, final String resourceFile) throws IOException { public static <T> boolean extractResourceToUserConfigDir(final Class<T> resourceClass, final String resourceFile, boolean overWrite) throws IOException {
final File userDir = new File(getUserConfigDirectory()); final File userDir = new File(getUserConfigDirectory());
final File resourceFileF = new File(userDir + File.separator + resourceFile); final File resourceFileF = new File(userDir + File.separator + resourceFile);
if (resourceFileF.exists()) { if (resourceFileF.exists() && !overWrite) {
return false; return false;
} }

View File

@ -70,7 +70,7 @@ public class XMLUtil {
*/ */
public static <T> boolean xmlIsValid(DOMSource xmlfile, Class<T> clazz, String schemaFile) { public static <T> boolean xmlIsValid(DOMSource xmlfile, Class<T> clazz, String schemaFile) {
try{ try{
PlatformUtil.extractResourceToUserConfigDir(clazz, schemaFile); PlatformUtil.extractResourceToUserConfigDir(clazz, schemaFile, false);
File schemaLoc = new File(PlatformUtil.getUserConfigDirectory() + File.separator + schemaFile); File schemaLoc = new File(PlatformUtil.getUserConfigDirectory() + File.separator + schemaFile);
SchemaFactory schm = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); SchemaFactory schm = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
try{ try{

View File

@ -48,7 +48,7 @@ import org.sleuthkit.datamodel.VirtualDirectory;
// method could be implemented. If the different nodes are necessary, is it merely because of some misuse of the Visitor pattern somewhere? // method could be implemented. If the different nodes are necessary, is it merely because of some misuse of the Visitor pattern somewhere?
// 2. All of this would be much improved by not constructing nodes with actions, but this might be necessary with pushing of nodes rather than use of lookups to // 2. All of this would be much improved by not constructing nodes with actions, but this might be necessary with pushing of nodes rather than use of lookups to
// handle selections. // handle selections.
class DataModelActionsFactory { public class DataModelActionsFactory {
public static final String VIEW_SOURCE_FILE_IN_DIR = NbBundle public static final String VIEW_SOURCE_FILE_IN_DIR = NbBundle
.getMessage(DataModelActionsFactory.class, "DataModelActionsFactory.srcFileInDir.text"); .getMessage(DataModelActionsFactory.class, "DataModelActionsFactory.srcFileInDir.text");
public static final String VIEW_FILE_IN_DIR = NbBundle public static final String VIEW_FILE_IN_DIR = NbBundle
@ -60,7 +60,7 @@ class DataModelActionsFactory {
public static final String SEARCH_FOR_FILES_SAME_MD5 = NbBundle public static final String SEARCH_FOR_FILES_SAME_MD5 = NbBundle
.getMessage(DataModelActionsFactory.class, "DataModelActionsFactory.srfFileSameMD5.text"); .getMessage(DataModelActionsFactory.class, "DataModelActionsFactory.srfFileSameMD5.text");
static List<Action> getActions(File file, boolean isArtifactSource) { public static List<Action> getActions(File file, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file));
final FileNode fileNode = new FileNode(file); final FileNode fileNode = new FileNode(file);
@ -79,7 +79,7 @@ class DataModelActionsFactory {
return actions; return actions;
} }
static List<Action> getActions(LayoutFile file, boolean isArtifactSource) { public static List<Action> getActions(LayoutFile file, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file));
LayoutFileNode layoutFileNode = new LayoutFileNode(file); LayoutFileNode layoutFileNode = new LayoutFileNode(file);
@ -97,7 +97,7 @@ class DataModelActionsFactory {
return actions; return actions;
} }
static List<Action> getActions(Directory directory, boolean isArtifactSource) { public static List<Action> getActions(Directory directory, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory));
DirectoryNode directoryNode = new DirectoryNode(directory); DirectoryNode directoryNode = new DirectoryNode(directory);
@ -115,7 +115,7 @@ class DataModelActionsFactory {
return actions; return actions;
} }
static List<Action> getActions(VirtualDirectory directory, boolean isArtifactSource) { public static List<Action> getActions(VirtualDirectory directory, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), directory));
VirtualDirectoryNode directoryNode = new VirtualDirectoryNode(directory); VirtualDirectoryNode directoryNode = new VirtualDirectoryNode(directory);
@ -133,7 +133,7 @@ class DataModelActionsFactory {
return actions; return actions;
} }
static List<Action> getActions(LocalFile file, boolean isArtifactSource) { public static List<Action> getActions(LocalFile file, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file));
final LocalFileNode localFileNode = new LocalFileNode(file); final LocalFileNode localFileNode = new LocalFileNode(file);
@ -151,7 +151,7 @@ class DataModelActionsFactory {
return actions; return actions;
} }
static List<Action> getActions(DerivedFile file, boolean isArtifactSource) { public static List<Action> getActions(DerivedFile file, boolean isArtifactSource) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file)); actions.add(new ViewContextAction((isArtifactSource ? VIEW_SOURCE_FILE_IN_DIR : VIEW_FILE_IN_DIR), file));
final LocalFileNode localFileNode = new LocalFileNode(file); final LocalFileNode localFileNode = new LocalFileNode(file);
@ -169,7 +169,7 @@ class DataModelActionsFactory {
return actions; return actions;
} }
static List<Action> getActions(Content content, boolean isArtifactSource) { public static List<Action> getActions(Content content, boolean isArtifactSource) {
if (content instanceof File) { if (content instanceof File) {
return getActions((File)content, isArtifactSource); return getActions((File)content, isArtifactSource);
} }

View File

@ -100,3 +100,4 @@ ResultDeleteAction.actoinPerf.confDlg.delAllresults.details={0} Results Deletion
ResultDeleteAction.exception.invalidAction.msg=Invalid action type\: {0} ResultDeleteAction.exception.invalidAction.msg=Invalid action type\: {0}
ExtractUnallocAction.done.errMsg.title=Error Extracting ExtractUnallocAction.done.errMsg.title=Error Extracting
ExtractUnallocAction.done.errMsg.msg=Error extracting unallocated space\: {0} ExtractUnallocAction.done.errMsg.msg=Error extracting unallocated space\: {0}
ExtractAction.done.notifyMsg.extractErr=Error extracting files\: {0}

View File

@ -1,5 +1,5 @@
CTL_DirectoryTreeTopComponent=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30C4\u30EA\u30FC CTL_DirectoryTreeTopComponent=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30C4\u30EA\u30FC
HINT_DirectoryTreeTopComponent=\u3053\u308C\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30C4\u30EA\u30FC\u3067\u3059 HINT_DirectoryTreeTopComponent=\u3053\u308C\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30C4\u30EA\u30FC\u306E\u30A6\u30A3\u30F3\u30C9\u30A6\u3067\u3059
OpenIDE-Module-Name=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30C4\u30EA\u30FC OpenIDE-Module-Name=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30C4\u30EA\u30FC
FileSystemDetailsPanel.imgOffsetLabel.text=\u30A4\u30E1\u30FC\u30B8\u30AA\u30D5\u30BB\u30C3\u30C8\uFF1A FileSystemDetailsPanel.imgOffsetLabel.text=\u30A4\u30E1\u30FC\u30B8\u30AA\u30D5\u30BB\u30C3\u30C8\uFF1A
FileSystemDetailsPanel.fsTypeLabel.text=\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u30BF\u30A4\u30D7\uFF1A FileSystemDetailsPanel.fsTypeLabel.text=\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u30BF\u30A4\u30D7\uFF1A
@ -18,7 +18,6 @@ FileSystemDetailsPanel.jLabel1.text=\u30D5\u30A1\u30A4\u30EB\u8A73\u7D30\u60C5\u
FileSystemDetailsPanel.volumeIDLabel.text=\u30DC\u30EA\u30E5\u30FC\u30E0ID\uFF1A FileSystemDetailsPanel.volumeIDLabel.text=\u30DC\u30EA\u30E5\u30FC\u30E0ID\uFF1A
FileSystemDetailsPanel.blockSizeLabel.text=\u30D6\u30ED\u30C3\u30AF\u30B5\u30A4\u30BA\uFF1A FileSystemDetailsPanel.blockSizeLabel.text=\u30D6\u30ED\u30C3\u30AF\u30B5\u30A4\u30BA\uFF1A
FileSystemDetailsPanel.blockCountLabel.text=\u30D6\u30ED\u30C3\u30AF\u6570\uFF1A FileSystemDetailsPanel.blockCountLabel.text=\u30D6\u30ED\u30C3\u30AF\u6570\uFF1A
#todo better translation?
FileSystemDetailsPanel.rootInumLabel.text=\u30EB\u30FC\u30C8\u30E1\u30BF\u30C7\u30FC\u30BF\u30A8\u30F3\u30C8\u30EA\u30FC\uFF1A FileSystemDetailsPanel.rootInumLabel.text=\u30EB\u30FC\u30C8\u30E1\u30BF\u30C7\u30FC\u30BF\u30A8\u30F3\u30C8\u30EA\u30FC\uFF1A
FileSystemDetailsPanel.firstInumLabel.text=\u6700\u521D\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u30A8\u30F3\u30C8\u30EA\u30FC\uFF1A FileSystemDetailsPanel.firstInumLabel.text=\u6700\u521D\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u30A8\u30F3\u30C8\u30EA\u30FC\uFF1A
FileSystemDetailsPanel.lastInumLabel.text=\u6700\u5F8C\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u30A8\u30F3\u30C8\u30EA\u30FC\uFF1A FileSystemDetailsPanel.lastInumLabel.text=\u6700\u5F8C\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u30A8\u30F3\u30C8\u30EA\u30FC\uFF1A
@ -36,7 +35,7 @@ VolumeDetailsPanel.flagsLabel.text=\u30D5\u30E9\u30B0\uFF1A
VolumeDetailsPanel.jLabel1.text=\u30DC\u30EA\u30E5\u30FC\u30E0\u4E00\u822C\u60C5\u5831 VolumeDetailsPanel.jLabel1.text=\u30DC\u30EA\u30E5\u30FC\u30E0\u4E00\u822C\u60C5\u5831
VolumeDetailsPanel.OKButton.text=OK VolumeDetailsPanel.OKButton.text=OK
ImageDetailsPanel.imageInfoLabel.text=\u30A4\u30E1\u30FC\u30B8\u60C5\u5831 ImageDetailsPanel.imageInfoLabel.text=\u30A4\u30E1\u30FC\u30B8\u60C5\u5831
ImageDetailsPanel.imgNameLabel.text=\u540D\u79F0\uFF1A ImageDetailsPanel.imgNameLabel.text=\u540D\u524D\uFF1A
ImageDetailsPanel.imgNameValue.text=... ImageDetailsPanel.imgNameValue.text=...
ImageDetailsPanel.imgTypeLabel.text=\u30BF\u30A4\u30D7\uFF1A ImageDetailsPanel.imgTypeLabel.text=\u30BF\u30A4\u30D7\uFF1A
ImageDetailsPanel.imgTypeValue.text=... ImageDetailsPanel.imgTypeValue.text=...
@ -48,10 +47,10 @@ ImageDetailsPanel.imgTotalSizeLabel.text=\u5408\u8A08\u30B5\u30A4\u30BA\uFF1A
ImageDetailsPanel.imgHashValue.text=... ImageDetailsPanel.imgHashValue.text=...
ImageDetailsPanel.imgHashLabel.text=\u30CF\u30C3\u30B7\u30E5\u5024\uFF1A ImageDetailsPanel.imgHashLabel.text=\u30CF\u30C3\u30B7\u30E5\u5024\uFF1A
BlackboardArtifactTagTypeNode.displayName.text=\u7D50\u679C\u30BF\u30B0 BlackboardArtifactTagTypeNode.displayName.text=\u7D50\u679C\u30BF\u30B0
BlackboardArtifactTagTypeNode.createSheet.name.name=\u540D\u79F0 BlackboardArtifactTagTypeNode.createSheet.name.name=\u540D\u524D
BlackboardArtifactTagTypeNode.createSheet.name.displayName=\u540D\u79F0 BlackboardArtifactTagTypeNode.createSheet.name.displayName=\u540D\u524D
ChangeViewAction.menuItem.view=\u30D3\u30E5\u30FC ChangeViewAction.menuItem.view=\u30D3\u30E5\u30FC
ChangeViewAction.menuItem.view.hex=Hex ChangeViewAction.menuItem.view.hex=HEX
ChangeViewAction.menuItem.view.string=\u30B9\u30C8\u30EA\u30F3\u30B0 ChangeViewAction.menuItem.view.string=\u30B9\u30C8\u30EA\u30F3\u30B0
DataResultFilterNode.action.viewFileInDir.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5185\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u8868\u793A DataResultFilterNode.action.viewFileInDir.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5185\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u8868\u793A
DataResultFilterNode.action.viewSrcFileInDir.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5185\u306E\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3092\u8868\u793A DataResultFilterNode.action.viewSrcFileInDir.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u5185\u306E\u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u3092\u8868\u793A
@ -62,9 +61,9 @@ DataResultFilterNode.action.viewInDir.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\
DirectoryTreeFilterNode.action.openFileSrcByAttr.text=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u3092\u958B\u304F DirectoryTreeFilterNode.action.openFileSrcByAttr.text=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22\u3092\u958B\u304F
DirectoryTreeFilterNode.action.runIngestMods.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C DirectoryTreeFilterNode.action.runIngestMods.text=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u5B9F\u884C
DirectoryTreeTopComponent.title.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30EA\u30B9\u30C6\u30A3\u30F3\u30B0 DirectoryTreeTopComponent.title.text=\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u30EA\u30B9\u30C6\u30A3\u30F3\u30B0
DirectoryTreeTopComponent.action.viewArtContent.text=\u6210\u679C\u7269\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u8868\u793A DirectoryTreeTopComponent.action.viewArtContent.text=\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u30B3\u30F3\u30C6\u30F3\u30C4\u3092\u8868\u793A
DirectoryTreeTopComponent.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC DirectoryTreeTopComponent.moduleErr=\u30E2\u30B8\u30E5\u30FC\u30EB\u30A8\u30E9\u30FC
DirectoryTreeTopComponent.moduleErr.msg=DirectoryTreeTopComponent\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u30ED\u30B0\u3067\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 DirectoryTreeTopComponent.moduleErr.msg=DirectoryTreeTopComponent\u30A2\u30C3\u30D7\u30C7\u30FC\u30C8\u3092\u78BA\u8A8D\u4E2D\u306B\u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u30A8\u30E9\u30FC\u3092\u8D77\u3053\u3057\u307E\u3057\u305F\u3002\u3069\u306E\u30E2\u30B8\u30E5\u30FC\u30EB\u304B\u30ED\u30B0\u3067\u78BA\u8A8D\u3057\u3066\u4E0B\u3055\u3044\u3002\u4E00\u90E8\u306E\u30C7\u30FC\u30BF\u304C\u4E0D\u5B8C\u5168\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002
ExplorerNodeActionVisitor.action.imgDetails.title=\u30A4\u30E1\u30FC\u30B8\u8A73\u7D30 ExplorerNodeActionVisitor.action.imgDetails.title=\u30A4\u30E1\u30FC\u30B8\u8A73\u7D30
ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u5185\u306E\u30C7\u30FC\u30BF\u3092\u8907\u6570\u306E\u30B7\u30F3\u30B0\u30EB\u30D5\u30A1\u30A4\u30EB\u306B\u62BD\u51FA ExplorerNodeActionVisitor.action.extUnallocToSingleFiles=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u5185\u306E\u30C7\u30FC\u30BF\u3092\u8907\u6570\u306E\u30B7\u30F3\u30B0\u30EB\u30D5\u30A1\u30A4\u30EB\u306B\u62BD\u51FA
ExplorerNodeActionVisitor.action.fileSystemDetails.title=\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u8A73\u7D30 ExplorerNodeActionVisitor.action.fileSystemDetails.title=\u30D5\u30A1\u30A4\u30EB\u30B7\u30B9\u30C6\u30E0\u8A73\u7D30
@ -72,9 +71,9 @@ ExplorerNodeActionVisitor.action.volumeDetails.title=\u30DC\u30EA\u30E5\u30FC\u3
ExplorerNodeActionVisitor.action.extUnallocToSingleFile=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u5185\u306E\u30C7\u30FC\u30BF\u3092\u4E00\u3064\u306E\u30B7\u30F3\u30B0\u30EB\u30D5\u30A1\u30A4\u30EB\u306B\u62BD\u51FA ExplorerNodeActionVisitor.action.extUnallocToSingleFile=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u5185\u306E\u30C7\u30FC\u30BF\u3092\u4E00\u3064\u306E\u30B7\u30F3\u30B0\u30EB\u30D5\u30A1\u30A4\u30EB\u306B\u62BD\u51FA
ExplorerNodeActionVisitor.volDetail.noVolMatchErr=\u30A8\u30E9\u30FC\uFF1A\u4E00\u81F4\u3059\u308B\u30DC\u30EA\u30E5\u30FC\u30E0\u304C\u3042\u308A\u307E\u305B\u3093\u3002 ExplorerNodeActionVisitor.volDetail.noVolMatchErr=\u30A8\u30E9\u30FC\uFF1A\u4E00\u81F4\u3059\u308B\u30DC\u30EA\u30E5\u30FC\u30E0\u304C\u3042\u308A\u307E\u305B\u3093\u3002
ExplorerNodeActionVisitor.imgDetail.noVolMatchesErr=\u30A8\u30E9\u30FC\uFF1A\u4E00\u81F4\u3059\u308B\u30DC\u30EA\u30E5\u30FC\u30E0\u304C\u3042\u308A\u307E\u305B\u3093\u3002 ExplorerNodeActionVisitor.imgDetail.noVolMatchesErr=\u30A8\u30E9\u30FC\uFF1A\u4E00\u81F4\u3059\u308B\u30DC\u30EA\u30E5\u30FC\u30E0\u304C\u3042\u308A\u307E\u305B\u3093\u3002
ExplorerNodeActionVisitor.exception.probGetParent.text={0}\: {1}\u304B\u3089\u30DA\u30A2\u30EC\u30F3\u30C8\u3092\u5165\u624B\u3059\u308B\u969B\u306B\u554F\u984C\u304C\u767A\u751F\u3057\u307E\u3057\u305F ExplorerNodeActionVisitor.exception.probGetParent.text={0}\: {1}\u304B\u3089\u30DA\u30A2\u30EC\u30F3\u30C8\u3092\u53D6\u5F97\u3059\u308B\u969B\u306B\u554F\u984C\u304C\u767A\u751F\u3057\u307E\u3057\u305F
ExtractAction.title.extractFiles.text=\u30D5\u30A1\u30A4\u30EB\u3092\u62BD\u51FA ExtractAction.title.extractFiles.text=\u30D5\u30A1\u30A4\u30EB\u3092\u62BD\u51FA
ExtractAction.extractFiles.cantCreateFolderErr.msg=\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A9\u30EB\u30C0\u30FC\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 ExtractAction.extractFiles.cantCreateFolderErr.msg=\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A9\u30EB\u30C0\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002
ExtractAction.confDlg.destFileExist.msg=\u4FDD\u5B58\u5148\u306E\u30D5\u30A1\u30A4\u30EB{0}\u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3001\u4E0A\u66F8\u304D\u3057\u307E\u3059\u304B\uFF1F ExtractAction.confDlg.destFileExist.msg=\u4FDD\u5B58\u5148\u306E\u30D5\u30A1\u30A4\u30EB{0}\u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3001\u4E0A\u66F8\u304D\u3057\u307E\u3059\u304B\uFF1F
ExtractAction.confDlg.destFileExist.title=\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u3059 ExtractAction.confDlg.destFileExist.title=\u30D5\u30A1\u30A4\u30EB\u304C\u5B58\u5728\u3057\u307E\u3059
ExtractAction.msgDlg.cantOverwriteFile.msg=\u65E2\u5B58\u30D5\u30A1\u30A4\u30EB{0}\u3092\u4E0A\u66F8\u304D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F ExtractAction.msgDlg.cantOverwriteFile.msg=\u65E2\u5B58\u30D5\u30A1\u30A4\u30EB{0}\u3092\u4E0A\u66F8\u304D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F
@ -85,7 +84,6 @@ ExtractAction.done.notifyMsg.fileExtr.text=\u30D5\u30A1\u30A4\u30EB\u304C\u62BD\
ExtractUnallocAction.notifyMsg.unallocAlreadyBeingExtr.msg=\u3053\u306E\u30A4\u30E1\u30FC\u30B8\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30C7\u30FC\u30BF\u306F\u65E2\u306B\u62BD\u51FA\u4E2D\u3067\u3059\u3002\u5225\u306E\u30A4\u30E1\u30FC\u30B8\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\u3002 ExtractUnallocAction.notifyMsg.unallocAlreadyBeingExtr.msg=\u3053\u306E\u30A4\u30E1\u30FC\u30B8\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30C7\u30FC\u30BF\u306F\u65E2\u306B\u62BD\u51FA\u4E2D\u3067\u3059\u3002\u5225\u306E\u30A4\u30E1\u30FC\u30B8\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\u3002
ExtractUnallocAction.msgDlg.folderDoesntExist.msg=\u30D5\u30A9\u30EB\u30C0\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002\u7D9A\u884C\u3059\u308B\u524D\u306B\u6709\u52B9\u306A\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\u3002 ExtractUnallocAction.msgDlg.folderDoesntExist.msg=\u30D5\u30A9\u30EB\u30C0\u306F\u5B58\u5728\u3057\u307E\u305B\u3093\u3002\u7D9A\u884C\u3059\u308B\u524D\u306B\u6709\u52B9\u306A\u30D5\u30A9\u30EB\u30C0\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044\u3002
ExtractUnallocAction.dlgTitle.selectDirToSaveTo.msg=\u4FDD\u5B58\u5148\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044 ExtractUnallocAction.dlgTitle.selectDirToSaveTo.msg=\u4FDD\u5B58\u5148\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E\u3057\u3066\u4E0B\u3055\u3044
#todo check meaning
ExtractUnallocAction.confDlg.unallocFileAlreadyExist.msg=\u3053\u306E\u30DC\u30EA\u30E5\u30FC\u30E0\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30D5\u30A1\u30A4\u30EB{0}\u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u65E2\u5B58\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u7F6E\u304D\u63DB\u3048\u307E\u3059\u304B\uFF1F ExtractUnallocAction.confDlg.unallocFileAlreadyExist.msg=\u3053\u306E\u30DC\u30EA\u30E5\u30FC\u30E0\u306E\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30D5\u30A1\u30A4\u30EB{0}\u306F\u65E2\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u65E2\u5B58\u306E\u30D5\u30A1\u30A4\u30EB\u3092\u7F6E\u304D\u63DB\u3048\u307E\u3059\u304B\uFF1F
ExtractUnallocAction.progress.extractUnalloc.title=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30C7\u30FC\u30BF\u3092\u62BD\u51FA\u4E2D ExtractUnallocAction.progress.extractUnalloc.title=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30C7\u30FC\u30BF\u3092\u62BD\u51FA\u4E2D
ExtractUnallocAction.progress.displayName.cancelling.text=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30C7\u30FC\u30BF\u3092\u62BD\u51FA\u4E2D\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09 ExtractUnallocAction.progress.displayName.cancelling.text=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u30C7\u30FC\u30BF\u3092\u62BD\u51FA\u4E2D\uFF08\u30AD\u30E3\u30F3\u30BB\u30EB\u4E2D\u2026\uFF09
@ -98,3 +96,4 @@ ResultDeleteAction.exception.invalidAction.msg=\u7121\u52B9\u306A\u30A2\u30AF\u3
ExtractUnallocAction.done.errMsg.title=\u62BD\u51FA\u30A8\u30E9\u30FC ExtractUnallocAction.done.errMsg.title=\u62BD\u51FA\u30A8\u30E9\u30FC
ExtractUnallocAction.done.errMsg.msg=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u62BD\u51FA\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A{0} ExtractUnallocAction.done.errMsg.msg=\u672A\u5272\u308A\u5F53\u3066\u9818\u57DF\u306E\u62BD\u51FA\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A{0}
DirectoryTreeFilterNode.action.collapseAll.text=\u3059\u3079\u3066\u30B3\u30E9\u30D7\u30B9 DirectoryTreeFilterNode.action.collapseAll.text=\u3059\u3079\u3066\u30B3\u30E9\u30D7\u30B9
ExtractAction.done.notifyMsg.extractErr=\u4E0B\u8A18\u306E\u30D5\u30A1\u30A4\u30EB\u306E\u62BD\u51FA\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\uFF1A {0}

View File

@ -33,7 +33,7 @@ import org.openide.util.lookup.ProxyLookup;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.datamodel.AbstractContentNode; import org.sleuthkit.autopsy.datamodel.AbstractContentNode;
import org.sleuthkit.autopsy.datamodel.DisplayableItemNode; import org.sleuthkit.autopsy.datamodel.DisplayableItemNode;
import org.sleuthkit.autopsy.ingest.IngestDialog; import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.Directory;
@ -116,7 +116,7 @@ class DirectoryTreeFilterNode extends FilterNode {
NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.runIngestMods.text")) { NbBundle.getMessage(this.getClass(), "DirectoryTreeFilterNode.action.runIngestMods.text")) {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
final IngestDialog ingestDialog = new IngestDialog(); final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog();
ingestDialog.setDataSources(Collections.<Content>singletonList(content)); ingestDialog.setDataSources(Collections.<Content>singletonList(content));
ingestDialog.display(); ingestDialog.display();
} }

View File

@ -73,6 +73,7 @@ import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/** /**
* Top component which displays something. * Top component which displays something.
*/ */
@ -82,7 +83,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
private transient ExplorerManager em = new ExplorerManager(); private transient ExplorerManager em = new ExplorerManager();
private static DirectoryTreeTopComponent instance; private static DirectoryTreeTopComponent instance;
private DataResultTopComponent dataResult = new DataResultTopComponent(true, NbBundle.getMessage(this.getClass(), private DataResultTopComponent dataResult = new DataResultTopComponent(true, NbBundle.getMessage(this.getClass(),
"DirectoryTreeTopComponent.title.text")); "DirectoryTreeTopComponent.title.text"));
private LinkedList<String[]> backList; private LinkedList<String[]> backList;
private LinkedList<String[]> forwardList; private LinkedList<String[]> forwardList;
/** /**
@ -543,8 +544,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
// The current case has been closed. Reset the ExplorerManager. // The current case has been closed. Reset the ExplorerManager.
Node emptyNode = new AbstractNode(Children.LEAF); Node emptyNode = new AbstractNode(Children.LEAF);
em.setRootContext(emptyNode); em.setRootContext(emptyNode);
} } else if (newValue != null) {
else if (newValue != null) {
// A new case has been opened. Reset the forward and back // A new case has been opened. Reset the forward and back
// buttons. Note that a call to CoreComponentControl.openCoreWindows() // buttons. Note that a call to CoreComponentControl.openCoreWindows()
// by the new Case object will lead to a componentOpened() call // by the new Case object will lead to a componentOpened() call
@ -598,7 +598,8 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
refreshTree(event.getArtifactType()); refreshTree(event.getArtifactType());
} }
}); });
} else if (changed.equals(IngestEvent.COMPLETED.toString())) { } else if (changed.equals(IngestEvent.INGEST_JOB_COMPLETED.toString())
|| changed.equals(IngestEvent.INGEST_JOB_CANCELLED.toString())) {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
@ -668,8 +669,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode);
} }
} } else if (originNode.getLookup().lookup(String.class) != null) {
else if (originNode.getLookup().lookup(String.class) != null) {
displayName = originNode.getLookup().lookup(String.class); displayName = originNode.getLookup().lookup(String.class);
} }
dataResult.setPath(displayName); dataResult.setPath(displayName);
@ -752,8 +752,6 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
pcs.removePropertyChangeListener(listener); pcs.removePropertyChangeListener(listener);
} }
/** /**
* Gets the tree on this DirectoryTreeTopComponent. * Gets the tree on this DirectoryTreeTopComponent.
* *
@ -768,11 +766,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
*/ */
public void refreshContentTreeSafe() { public void refreshContentTreeSafe() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(new Runnable() {
@Override @Override
public void run() { public void run() {
refreshContentTree(); refreshContentTree();
} }
}); });
} }
/** /**
@ -881,13 +879,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
while (null == selectedNode && !selectedNodePath.isEmpty()) { while (null == selectedNode && !selectedNodePath.isEmpty()) {
try { try {
selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(new String[0])); selectedNode = NodeOp.findPath(em.getRootContext(), selectedNodePath.toArray(new String[0]));
} } catch (NodeNotFoundException ex) {
catch (NodeNotFoundException ex) {
// The selected node may have been deleted (e.g., a deleted tag), so truncate the path and try again. // The selected node may have been deleted (e.g., a deleted tag), so truncate the path and try again.
if (selectedNodePath.size() > 1) { if (selectedNodePath.size() > 1) {
selectedNodePath.remove(selectedNodePath.size() - 1); selectedNodePath.remove(selectedNodePath.size() - 1);
} } else {
else {
StringBuilder nodePath = new StringBuilder(); StringBuilder nodePath = new StringBuilder();
for (int i = 0; i < previouslySelectedNodePath.length; ++i) { for (int i = 0; i < previouslySelectedNodePath.length; ++i) {
nodePath.append(previouslySelectedNodePath[i]).append("/"); nodePath.append(previouslySelectedNodePath[i]).append("/");
@ -906,8 +902,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
} }
try { try {
em.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode}); em.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode});
} } catch (PropertyVetoException ex) {
catch (PropertyVetoException ex) {
logger.log(Level.WARNING, "Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex); logger.log(Level.WARNING, "Property veto from ExplorerManager setting selection to " + selectedNode.getName(), ex);
} }
} }
@ -970,11 +965,11 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
} catch (TskException ex) { } catch (TskException ex) {
logger.log(Level.WARNING, "Error retrieving attributes", ex); logger.log(Level.WARNING, "Error retrieving attributes", ex);
} }
} else if ( type.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT) || } else if (type.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT)
type.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT) ) { || type.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT)) {
Node interestingItemsRootNode = resultsChilds.findChild(type.getLabel()); Node interestingItemsRootNode = resultsChilds.findChild(type.getLabel());
Children interestingItemsRootChildren = interestingItemsRootNode.getChildren(); Children interestingItemsRootChildren = interestingItemsRootNode.getChildren();
try { try {
String setName = null; String setName = null;
List<BlackboardAttribute> attributes = art.getAttributes(); List<BlackboardAttribute> attributes = art.getAttributes();
for (BlackboardAttribute att : attributes) { for (BlackboardAttribute att : attributes) {
@ -1033,13 +1028,12 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat
try { try {
firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1); firePropertyChange(BlackboardResultViewer.FINISHED_DISPLAY_EVT, 0, 1);
} } catch (Exception e) {
catch (Exception e) {
logger.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e); logger.log(Level.SEVERE, "DirectoryTreeTopComponent listener threw exception", e);
MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"), MessageNotifyUtil.Notify.show(NbBundle.getMessage(this.getClass(), "DirectoryTreeTopComponent.moduleErr"),
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"DirectoryTreeTopComponent.moduleErr.msg"), "DirectoryTreeTopComponent.moduleErr.msg"),
MessageNotifyUtil.MessageType.ERROR); MessageNotifyUtil.MessageType.ERROR);
} }
} }
} }

View File

@ -241,7 +241,8 @@ public final class ExtractAction extends AbstractAction {
} }
catch (Exception ex) { catch (Exception ex) {
logger.log(Level.SEVERE, "Fatal error during file extraction", ex); logger.log(Level.SEVERE, "Fatal error during file extraction", ex);
MessageNotifyUtil.Message.info("Error extracting files: " + ex.getMessage()); MessageNotifyUtil.Message.info(
NbBundle.getMessage(this.getClass(), "ExtractAction.done.notifyMsg.extractErr", ex.getMessage()));
msgDisplayed = true; msgDisplayed = true;
} }
finally { finally {

View File

@ -1,4 +1,4 @@
# To change this template, choose Tools | Templates
# and open the template in the editor.
SampleContentViewer.jLabel1.text=jLabel1 SampleContentViewer.jLabel1.text=jLabel1
SampleIngestModuleFactory.moduleName=Sample Ingest Module
SampleIngestModuleFactory.moduleDescription=This module serves as a sample ingest module for software developers.
SampleIngestModuleIngestJobSettingsPanel.skipKnownFilesCheckBox.text=Skip Known Files (NSRL)

View File

@ -29,56 +29,131 @@
*/ */
package org.sleuthkit.autopsy.examples; package org.sleuthkit.autopsy.examples;
import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.log4j.Logger; import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
import org.sleuthkit.autopsy.casemodule.services.Services; import org.sleuthkit.autopsy.casemodule.services.Services;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleStatusHelper;
import org.sleuthkit.autopsy.ingest.IngestModule; import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleAdapter;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.FsContent;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleAdapter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.datamodel.TskData;
/** /**
* Sample data source ingest module that doesn't do much. Note that the * Sample data source ingest module that doesn't do much. Demonstrates per
* IngestModuleAdapter abstract class could have been used as a base class to * ingest job module settings, use of a subset of the available ingest services
* obtain default implementations of many of the DataSourceIngestModule methods. * and thread-safe sharing of per ingest job data.
*/ */
// RJCTODO: Remove inheritance from IngestModuleAdapter to show full implementation of interface
// provide better documentation, and provide more extensive demonstration of how to
// use various ingest services.
class SampleDataSourceIngestModule extends IngestModuleAdapter implements DataSourceIngestModule { class SampleDataSourceIngestModule extends IngestModuleAdapter implements DataSourceIngestModule {
private static final Logger logger = Logger.getLogger(SampleDataSourceIngestModule.class); private static final HashMap<Long, Long> fileCountsForIngestJobs = new HashMap<>();
private final boolean skipKnownFiles;
private IngestJobContext context = null;
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
SampleDataSourceIngestModule(SampleModuleIngestJobSettings settings) {
this.skipKnownFiles = settings.skipKnownFiles();
}
@Override @Override
public ProcessResult process(Content dataSource, DataSourceIngestModuleStatusHelper statusHelper) { public void startUp(IngestJobContext context) throws IngestModuleException {
Case case1 = Case.getCurrentCase(); this.context = context;
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
// This method is thread-safe with per ingest job reference counted
// management of shared data.
initFileCount(context.getJobId());
}
@Override
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
// There are two tasks to do. Set the the progress bar to determinate
// and set the remaining number of work units to be completed to two.
progressBar.switchToDeterminate(2);
Case autopsyCase = Case.getCurrentCase();
SleuthkitCase sleuthkitCase = autopsyCase.getSleuthkitCase();
Services services = new Services(sleuthkitCase); Services services = new Services(sleuthkitCase);
FileManager fileManager = services.getFileManager(); FileManager fileManager = services.getFileManager();
try { try {
// Get count of files with .doc extension.
long fileCount = 0;
List<AbstractFile> docFiles = fileManager.findFiles(dataSource, "%.doc"); List<AbstractFile> docFiles = fileManager.findFiles(dataSource, "%.doc");
for (AbstractFile file : docFiles) { for (AbstractFile docFile : docFiles) {
// do something with each doc file if (!skipKnownFiles || docFile.getKnown() != TskData.FileKnown.KNOWN) {
++fileCount;
}
} }
progressBar.progress(1);
// Get files by creation time.
long currentTime = System.currentTimeMillis() / 1000; long currentTime = System.currentTimeMillis() / 1000;
long minTime = currentTime - (14 * 24 * 60 * 60); // Go back two weeks. long minTime = currentTime - (14 * 24 * 60 * 60); // Go back two weeks.
List<FsContent> otherFiles = sleuthkitCase.findFilesWhere("crtime > " + minTime); List<FsContent> otherFiles = sleuthkitCase.findFilesWhere("crtime > " + minTime);
// do something with these files... for (FsContent otherFile : otherFiles) {
if (!skipKnownFiles || otherFile.getKnown() != TskData.FileKnown.KNOWN) {
++fileCount;
}
}
// This method is thread-safe with per ingest job reference counted
// management of shared data.
addToFileCount(context.getJobId(), fileCount);
progressBar.progress(1);
return IngestModule.ProcessResult.OK;
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.fatal("Error retrieving files from database: " + ex.getLocalizedMessage()); IngestServices ingestServices = IngestServices.getInstance();
return IngestModule.ProcessResult.OK; Logger logger = ingestServices.getLogger(SampleIngestModuleFactory.getModuleName());
logger.log(Level.SEVERE, "File query failed", ex);
return IngestModule.ProcessResult.ERROR;
} }
return IngestModule.ProcessResult.OK;
} }
@Override
public void shutDown(boolean ingestJobCancelled) {
// This method is thread-safe with per ingest job reference counted
// management of shared data.
postFileCount(context.getJobId());
}
synchronized static void initFileCount(long ingestJobId) {
Long refCount = refCounter.incrementAndGet(ingestJobId);
if (refCount == 1) {
fileCountsForIngestJobs.put(ingestJobId, 0L);
}
}
synchronized static void addToFileCount(long ingestJobId, long countToAdd) {
Long fileCount = fileCountsForIngestJobs.get(ingestJobId);
fileCount += countToAdd;
fileCountsForIngestJobs.put(ingestJobId, fileCount);
}
synchronized static void postFileCount(long ingestJobId) {
Long refCount = refCounter.decrementAndGet(ingestJobId);
if (refCount == 0) {
Long filesCount = fileCountsForIngestJobs.remove(ingestJobId);
String msgText = String.format("Found %d files", filesCount);
IngestMessage message = IngestMessage.createMessage(
IngestMessage.MessageType.DATA,
SampleIngestModuleFactory.getModuleName(),
msgText);
IngestServices.getInstance().postMessage(message);
}
}
} }

View File

@ -29,85 +29,103 @@
*/ */
package org.sleuthkit.autopsy.examples; package org.sleuthkit.autopsy.examples;
import org.apache.log4j.Logger; import java.util.HashMap;
import org.openide.util.Exceptions; import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestModule; import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleAdapter;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleAdapter;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
/** /**
* This is a sample and simple module. It is a file-level ingest module, meaning * Sample file ingest module that doesn't do much. Demonstrates per ingest job
* that it will get called on each file in the disk image / logical file set. It * module settings, use of a subset of the available ingest services and
* does a stupid calculation of the number of null bytes in the beginning of the * thread-safe sharing of per ingest job data.
* file in order to show the basic flow.
*
* Autopsy has been hard coded to ignore this module based on the it's package
* name. IngestModuleLoader will not load things from the
* org.sleuthkit.autopsy.examples package. Either change the package or the
* loading code to make this module actually run.
*/ */
// RJCTODO: Remove inheritance from IngestModuleAdapter to show full implementation of interface
// provide better documentation, and provide more extensive demonstration of how to
// use various ingest services.
class SampleFileIngestModule extends IngestModuleAdapter implements FileIngestModule { class SampleFileIngestModule extends IngestModuleAdapter implements FileIngestModule {
private int attrId = -1; private static final HashMap<Long, Long> artifactCountsForIngestJobs = new HashMap<>();
private static int attrId = -1;
private final boolean skipKnownFiles;
private IngestJobContext context = null;
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
@Override SampleFileIngestModule(SampleModuleIngestJobSettings settings) {
public void startUp(IngestJobContext initContext) { this.skipKnownFiles = settings.skipKnownFiles();
/* For this demo, we are going to make a private attribute to post our
* results to the blackbaord with. There are many standard blackboard artifact
* and attribute types and you should first consider using one of those before
* making private ones because other modules won't know about provate ones.
* Because our demo has results that have no real value, we do not have an
* official attribute for them.
*/
Case case1 = Case.getCurrentCase();
SleuthkitCase sleuthkitCase = case1.getSleuthkitCase();
// see if the type already exists in the blackboard.
try {
attrId = sleuthkitCase.getAttrTypeID("ATTR_SAMPLE");
} catch (TskCoreException ex) {
// create it if not
try {
attrId = sleuthkitCase.addAttrType("ATTR_SAMPLE", "Sample Attribute");
} catch (TskCoreException ex1) {
Logger log = Logger.getLogger(SampleFileIngestModule.class);
log.fatal("Error adding attribute type: " + ex1.getLocalizedMessage());
attrId = -1;
}
}
} }
@Override @Override
public IngestModule.ProcessResult process(AbstractFile abstractFile) { public void startUp(IngestJobContext context) throws IngestModuleException {
// skip non-files this.context = context;
if ((abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| (abstractFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)) { synchronized (SampleFileIngestModule.class) {
if (attrId == -1) {
// For this sample, make a new attribute type to use to post
// results to the blackboard. There are many standard blackboard
// artifact and attribute types and you should use them instead
// creating new ones to facilitate use of your results by other
// modules.
Case autopsyCase = Case.getCurrentCase();
SleuthkitCase sleuthkitCase = autopsyCase.getSleuthkitCase();
// See if the attribute type has already been defined.
try {
attrId = sleuthkitCase.getAttrTypeID("ATTR_SAMPLE");
} catch (TskCoreException e) {
// If not, create the the attribute type.
try {
attrId = sleuthkitCase.addAttrType("ATTR_SAMPLE", "Sample Attribute");
} catch (TskCoreException ex) {
IngestServices ingestServices = IngestServices.getInstance();
Logger logger = ingestServices.getLogger(SampleIngestModuleFactory.getModuleName());
logger.log(Level.SEVERE, "Failed to create blackboard attribute", ex);
attrId = -1;
throw new IngestModuleException(ex.getLocalizedMessage());
}
}
}
}
// This method is thread-safe with per ingest job reference counted
// management of shared data.
initBlackboardPostCount(context.getJobId());
}
@Override
public IngestModule.ProcessResult process(AbstractFile file) {
if (attrId != -1) {
return IngestModule.ProcessResult.ERROR;
}
// Skip anything other than actual file system files.
if ((file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| (file.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS)) {
return IngestModule.ProcessResult.OK; return IngestModule.ProcessResult.OK;
} }
// skip NSRL / known files // Skip NSRL / known files.
if (abstractFile.getKnown() == TskData.FileKnown.KNOWN) { if (skipKnownFiles && file.getKnown() == TskData.FileKnown.KNOWN) {
return IngestModule.ProcessResult.OK; return IngestModule.ProcessResult.OK;
} }
/* Do a non-sensical calculation of the number of 0x00 bytes // Do a nonsensical calculation of the number of 0x00 bytes
* in the first 1024-bytes of the file. This is for demo // in the first 1024-bytes of the file. This is for demo
* purposes only. // purposes only.
*/
try { try {
byte buffer[] = new byte[1024]; byte buffer[] = new byte[1024];
int len = abstractFile.read(buffer, 0, 1024); int len = file.read(buffer, 0, 1024);
int count = 0; int count = 0;
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
if (buffer[i] == 0x00) { if (buffer[i] == 0x00) {
@ -115,23 +133,64 @@ class SampleFileIngestModule extends IngestModuleAdapter implements FileIngestMo
} }
} }
if (attrId != -1) { // Make an attribute using the ID for the attribute type that
// Make an attribute using the ID for the private type that we previously created. // was previously created.
BlackboardAttribute attr = new BlackboardAttribute(attrId, "SampleFileIngestModule", count); // RJCTODO: Set up factory with static module name function as example BlackboardAttribute attr = new BlackboardAttribute(attrId, SampleIngestModuleFactory.getModuleName(), count);
/* add it to the general info artifact. In real modules, you would likely have // Add the to the general info artifact for the file. In a
* more complex data types and be making more specific artifacts. // real module, you would likely have more complex data types
*/ // and be making more specific artifacts.
BlackboardArtifact art = abstractFile.getGenInfoArtifact(); BlackboardArtifact art = file.getGenInfoArtifact();
art.addAttribute(attr); art.addAttribute(attr);
}
// This method is thread-safe with per ingest job reference counted
// management of shared data.
addToBlackboardPostCount(context.getJobId(), 1L);
// Fire an event to notify any listeners for blackboard postings.
ModuleDataEvent event = new ModuleDataEvent(SampleIngestModuleFactory.getModuleName(), ARTIFACT_TYPE.TSK_GEN_INFO);
IngestServices.getInstance().fireModuleDataEvent(event);
return IngestModule.ProcessResult.OK; return IngestModule.ProcessResult.OK;
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
Exceptions.printStackTrace(ex); IngestServices ingestServices = IngestServices.getInstance();
Logger logger = ingestServices.getLogger(SampleIngestModuleFactory.getModuleName());
logger.log(Level.SEVERE, "Error processing file (id = " + file.getId() + ")", ex);
return IngestModule.ProcessResult.ERROR; return IngestModule.ProcessResult.ERROR;
} }
} }
// RJCTODO: Add a module factory with service provider annotation (commented out) @Override
public void shutDown(boolean ingestJobCancelled) {
// This method is thread-safe with per ingest job reference counted
// management of shared data.
reportBlackboardPostCount(context.getJobId());
}
synchronized static void initBlackboardPostCount(long ingestJobId) {
Long refCount = refCounter.incrementAndGet(ingestJobId);
if (refCount == 1) {
artifactCountsForIngestJobs.put(ingestJobId, 0L);
}
}
synchronized static void addToBlackboardPostCount(long ingestJobId, long countToAdd) {
Long fileCount = artifactCountsForIngestJobs.get(ingestJobId);
fileCount += countToAdd;
artifactCountsForIngestJobs.put(ingestJobId, fileCount);
}
synchronized static void reportBlackboardPostCount(long ingestJobId) {
Long refCount = refCounter.decrementAndGet(ingestJobId);
if (refCount == 0) {
Long filesCount = artifactCountsForIngestJobs.remove(ingestJobId);
String msgText = String.format("Posted %d times to the blackboard", filesCount);
IngestMessage message = IngestMessage.createMessage(
IngestMessage.MessageType.INFO,
SampleIngestModuleFactory.getModuleName(),
msgText);
IngestServices.getInstance().postMessage(message);
}
}
} }

View File

@ -0,0 +1,326 @@
/*
* Sample ingest module factory in the public domain.
* Feel free to use this as a template for your inget module factories.
*
* Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.sleuthkit.autopsy.examples;
// The following import is required for the ServiceProvider annotation (see
// below) used by the Autopsy ingest framework to locate ingest module
// factories. You will need to add a dependency on the Lookup API NetBeans
// module to your NetBeans module to use this import.
import org.openide.util.lookup.ServiceProvider;
// The following import is required to participate in Autopsy
// internationalization and localization. Autopsy core is currently localized
// for Japan. Please consult the NetBeans documentation for details.
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSetttingsPanel;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
/**
* A factory that creates sample data source and file ingest modules.
* <p>
* This factory implements an interface that must be implemented by all
* providers of Autopsy ingest modules. An ingest module factory is used to
* create instances of a type of data source ingest module, a type of file
* ingest module, or both.
* <p>
* Autopsy will generally use the factory to create several instances of each
* type of module for each ingest job it performs. Completing an ingest job
* entails processing a single data source (e.g., a disk image) and all of the
* files from the data source, including files extracted from archives and any
* unallocated space (made to look like a series of files). The data source is
* passed through one or more pipelines of data source ingest modules. The files
* are passed through one or more pipelines of file ingest modules.
* <p>
* Autopsy may use multiple threads to complete an ingest job, but it is
* guaranteed that there will be no more than one module instance per thread.
* However, if the module instances must share resources, the modules are
* responsible for synchronizing access to the shared resources and doing
* reference counting as required to release those resources correctly. Also,
* more than one ingest job may be in progress at any given time. This must also
* be taken into consideration when sharing resources between module instances.
* <p>
* An ingest module factory may provide global and per ingest job settings user
* interface panels. The global settings should apply to all module instances.
* The per ingest job settings should apply to all module instances working on a
* particular ingest job. Autopsy supports context-sensitive and persistent per
* ingest job settings, so per ingest job settings must be serializable.
* <p>
* To be discovered at runtime by the ingest framework, IngestModuleFactory
* implementations must be marked with the following NetBeans Service provider
* annotation (see below).
* <p>
* IMPORTANT TIP: This sample ingest module factory directly implements
* IngestModuleFactory. A practical alternative, recommended if you do not need
* to provide implementations of all of the IngestModuleFactory methods, is to
* extend the abstract class IngestModuleFactoryAdapter to get default
* implementations of most of the IngestModuleFactory methods.
*/
@ServiceProvider(service = IngestModuleFactory.class) // Sample is discarded at runtime
public class SampleIngestModuleFactory implements IngestModuleFactory {
private static final String VERSION_NUMBER = "1.0.0";
// This class method allows the ingest module instances created by this
// factory to use the same display name that is provided to the Autopsy
// ingest framework by the factory.
static String getModuleName() {
return NbBundle.getMessage(SampleIngestModuleFactory.class, "SampleIngestModuleFactory.moduleName");
}
/**
* Gets the display name that identifies the family of ingest modules the
* factory creates. Autopsy uses this string to identify the module in user
* interface components and log messages. The module name must be unique. so
* a brief but distinctive name is recommended.
*
* @return The module family display name.
*/
@Override
public String getModuleDisplayName() {
return getModuleName();
}
/**
* Gets a brief, user-friendly description of the family of ingest modules
* the factory creates. Autopsy uses this string to describe the module in
* user interface components.
*
* @return The module family description.
*/
@Override
public String getModuleDescription() {
return NbBundle.getMessage(SampleIngestModuleFactory.class, "SampleIngestModuleFactory.moduleDescription");
}
/**
* Gets the version number of the family of ingest modules the factory
* creates.
*
* @return The module family version number.
*/
@Override
public String getModuleVersionNumber() {
return VERSION_NUMBER;
}
/**
* Queries the factory to determine if it provides a user interface panel to
* allow a user to change settings that are used by all instances of the
* family of ingest modules the factory creates. For example, the Autopsy
* core hash lookup ingest module factory provides a global settings panel
* to import and create hash databases. The hash databases are then enabled
* or disabled per ingest job using an ingest job settings panel. If the
* module family does not have global settings, the factory may extend
* IngestModuleFactoryAdapter to get an implementation of this method that
* returns false.
*
* @return True if the factory provides a global settings panel.
*/
@Override
public boolean hasGlobalSettingsPanel() {
return false;
}
/**
* Gets a user interface panel that allows a user to change settings that
* are used by all instances of the family of ingest modules the factory
* creates. For example, the Autopsy core hash lookup ingest module factory
* provides a global settings panel to import and create hash databases. The
* imported hash databases are then enabled or disabled per ingest job using
* ingest an ingest job settings panel. If the module family does not have a
* global settings, the factory may extend IngestModuleFactoryAdapter to get
* an implementation of this method that throws an
* UnsupportedOperationException.
*
* @return A global settings panel.
*/
@Override
public IngestModuleGlobalSetttingsPanel getGlobalSettingsPanel() {
throw new UnsupportedOperationException();
}
/**
* Gets the default per ingest job settings for instances of the family of
* ingest modules the factory creates. For example, the Autopsy core hash
* lookup ingest modules family uses hash databases imported or created
* using its global settings panel. All of the hash databases are enabled by
* default for an ingest job. If the module family does not have per ingest
* job settings, the factory may extend IngestModuleFactoryAdapter to get an
* implementation of this method that returns an instance of the
* NoIngestModuleJobSettings class.
*
* @return The default ingest job settings.
*/
@Override
public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
return new SampleModuleIngestJobSettings();
}
/**
* Queries the factory to determine if it provides user a interface panel to
* allow a user to make per ingest job settings for instances of the family
* of ingest modules the factory creates. For example, the Autopsy core hash
* lookup ingest module factory provides an ingest job settings panels to
* enable or disable hash databases per ingest job. If the module family
* does not have per ingest job settings, the factory may extend
* IngestModuleFactoryAdapter to get an implementation of this method that
* returns false.
*
* @return True if the factory provides ingest job settings panels.
*/
@Override
public boolean hasIngestJobSettingsPanel() {
return true;
}
/**
* Gets a user interface panel that can be used to set per ingest job
* settings for instances of the family of ingest modules the factory
* creates. For example, the core hash lookup ingest module factory provides
* an ingest job settings panel to enable or disable hash databases per
* ingest job. If the module family does not have per ingest job settings,
* the factory may extend IngestModuleFactoryAdapter to get an
* implementation of this method that throws an
* UnsupportedOperationException.
*
* @param setting Per ingest job settings to initialize the panel.
* @return An ingest job settings panel.
*/
@Override
public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
if (!(settings instanceof SampleModuleIngestJobSettings)) {
throw new IllegalArgumentException("Expected settings argument to be instanceof SampleModuleIngestJobSettings");
}
return new SampleIngestModuleIngestJobSettingsPanel((SampleModuleIngestJobSettings) settings);
}
/**
* Queries the factory to determine if it is capable of creating data source
* ingest modules. If the module family does not include data source ingest
* modules, the factory may extend IngestModuleFactoryAdapter to get an
* implementation of this method that returns false.
*
* @return True if the factory can create data source ingest modules.
*/
@Override
public boolean isDataSourceIngestModuleFactory() {
return true;
}
/**
* Creates a data source ingest module instance.
* <p>
* Autopsy will generally use the factory to several instances of each type
* of module for each ingest job it performs. Completing an ingest job
* entails processing a single data source (e.g., a disk image) and all of
* the files from the data source, including files extracted from archives
* and any unallocated space (made to look like a series of files). The data
* source is passed through one or more pipelines of data source ingest
* modules. The files are passed through one or more pipelines of file
* ingest modules.
* <p>
* The ingest framework may use multiple threads to complete an ingest job,
* but it is guaranteed that there will be no more than one module instance
* per thread. However, if the module instances must share resources, the
* modules are responsible for synchronizing access to the shared resources
* and doing reference counting as required to release those resources
* correctly. Also, more than one ingest job may be in progress at any given
* time. This must also be taken into consideration when sharing resources
* between module instances. modules.
* <p>
* If the module family does not include data source ingest modules, the
* factory may extend IngestModuleFactoryAdapter to get an implementation of
* this method that throws an UnsupportedOperationException.
*
* @param settings The settings for the ingest job.
* @return A data source ingest module instance.
*/
@Override
public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings) {
if (!(settings instanceof SampleModuleIngestJobSettings)) {
throw new IllegalArgumentException("Expected settings argument to be instanceof SampleModuleIngestJobSettings");
}
return new SampleDataSourceIngestModule((SampleModuleIngestJobSettings) settings);
}
/**
* Queries the factory to determine if it is capable of creating file ingest
* modules. If the module family does not include file ingest modules, the
* factory may extend IngestModuleFactoryAdapter to get an implementation of
* this method that returns false.
*
* @return True if the factory can create file ingest modules.
*/
@Override
public boolean isFileIngestModuleFactory() {
return true;
}
/**
* Creates a file ingest module instance.
* <p>
* Autopsy will generally use the factory to several instances of each type
* of module for each ingest job it performs. Completing an ingest job
* entails processing a single data source (e.g., a disk image) and all of
* the files from the data source, including files extracted from archives
* and any unallocated space (made to look like a series of files). The data
* source is passed through one or more pipelines of data source ingest
* modules. The files are passed through one or more pipelines of file
* ingest modules.
* <p>
* The ingest framework may use multiple threads to complete an ingest job,
* but it is guaranteed that there will be no more than one module instance
* per thread. However, if the module instances must share resources, the
* modules are responsible for synchronizing access to the shared resources
* and doing reference counting as required to release those resources
* correctly. Also, more than one ingest job may be in progress at any given
* time. This must also be taken into consideration when sharing resources
* between module instances. modules.
* <p>
* If the module family does not include file ingest modules, the factory
* may extend IngestModuleFactoryAdapter to get an implementation of this
* method that throws an UnsupportedOperationException.
*
* @param settings The settings for the ingest job.
* @return A file ingest module instance.
*/
@Override
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) {
if (!(settings instanceof SampleModuleIngestJobSettings)) {
throw new IllegalArgumentException("Expected settings argument to be instanceof SampleModuleIngestJobSettings");
}
return new SampleFileIngestModule((SampleModuleIngestJobSettings) settings);
}
}

View File

@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.8" 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" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="skipKnownFilesCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="255" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="skipKnownFilesCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="270" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Component class="javax.swing.JCheckBox" name="skipKnownFilesCheckBox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/examples/Bundle.properties" key="SampleIngestModuleIngestJobSettingsPanel.skipKnownFilesCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Form>

View File

@ -0,0 +1,96 @@
/*
* Sample module ingest job settings panel in the public domain.
* Feel free to use this as a template for your module ingest job settings
* panels.
*
* Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.sleuthkit.autopsy.examples;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
/**
* UI component used to make per ingest job settings for sample ingest modules.
*/
public class SampleIngestModuleIngestJobSettingsPanel extends IngestModuleIngestJobSettingsPanel {
/**
* Creates new form SampleIngestModuleIngestJobSettings
*/
public SampleIngestModuleIngestJobSettingsPanel(SampleModuleIngestJobSettings settings) {
initComponents();
customizeComponents(settings);
}
private void customizeComponents(SampleModuleIngestJobSettings settings) {
skipKnownFilesCheckBox.setSelected(settings.skipKnownFiles());
}
/**
* Gets the ingest job settings for an ingest module.
*
* @return The ingest settings.
*/
@Override
public IngestModuleIngestJobSettings getSettings() {
return new SampleModuleIngestJobSettings(skipKnownFilesCheckBox.isSelected());
}
/**
* 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() {
skipKnownFilesCheckBox = new javax.swing.JCheckBox();
org.openide.awt.Mnemonics.setLocalizedText(skipKnownFilesCheckBox, org.openide.util.NbBundle.getMessage(SampleIngestModuleIngestJobSettingsPanel.class, "SampleIngestModuleIngestJobSettingsPanel.skipKnownFilesCheckBox.text")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(skipKnownFilesCheckBox)
.addContainerGap(255, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(skipKnownFilesCheckBox)
.addContainerGap(270, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox skipKnownFilesCheckBox;
// End of variables declaration//GEN-END:variables
}

View File

@ -0,0 +1,56 @@
/*
* Sample module ingest job settings in the public domain.
* Feel free to use this as a template for your module job settings.
*
* Contact: Brian Carrier [carrier <at> sleuthkit [dot] org]
*
* This is free and unencumbered software released into the public domain.
*
* Anyone is free to copy, modify, publish, use, compile, sell, or
* distribute this software, either in source code form or as a compiled
* binary, for any purpose, commercial or non-commercial, and by any
* means.
*
* In jurisdictions that recognize copyright laws, the author or authors
* of this software dedicate any and all copyright interest in the
* software to the public domain. We make this dedication for the benefit
* of the public at large and to the detriment of our heirs and
* successors. We intend this dedication to be an overt act of
* relinquishment in perpetuity of all present and future rights to this
* software under copyright law.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
package org.sleuthkit.autopsy.examples;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
/**
* Ingest job options for sample ingest module instances.
*/
public class SampleModuleIngestJobSettings implements IngestModuleIngestJobSettings {
private boolean skipKnownFiles = true;
SampleModuleIngestJobSettings() {
}
SampleModuleIngestJobSettings(boolean skipKnownFiles) {
this.skipKnownFiles = skipKnownFiles;
}
void setSkipKnownFiles(boolean enabled) {
skipKnownFiles = enabled;
}
boolean skipKnownFiles() {
return skipKnownFiles;
}
}

View File

@ -13,8 +13,8 @@ DateSearchPanel.accessedCheckBox.text=\u30A2\u30AF\u30BB\u30B9\u6E08\u307F
DateSearchPanel.changedCheckBox.text=\u5909\u66F4\u6E08\u307F DateSearchPanel.changedCheckBox.text=\u5909\u66F4\u6E08\u307F
DateSearchPanel.modifiedCheckBox.text=\u4FEE\u6B63\u6E08\u307F DateSearchPanel.modifiedCheckBox.text=\u4FEE\u6B63\u6E08\u307F
DateSearchPanel.jLabel1.text=to DateSearchPanel.jLabel1.text=to
NameSearchPanel.nameCheckBox.text=\u540D\u79F0\uFF1A NameSearchPanel.nameCheckBox.text=\u540D\u524D\uFF1A
NameSearchPanel.noteNameLabel.text=<html>*\u6CE8\u610F\uFF1A\u540D\u79F0\u30DE\u30C3\u30C1\u306F\u5927\u6587\u5B57\u3068\u5C0F\u6587\u5B57\u3092\u533A\u5225\u3057\u307E\u3059\u3002\u307E\u305F\u3001<br/> \u30D5\u30A1\u30A4\u30EB\u540D\u306E\u3044\u304B\u306A\u308B\u90E8\u5206\u3082\u30DE\u30C3\u30C1\u3057\u307E\u3059\u3002\u6B63\u898F\u8868\u73FE\u306F<br/>\u73FE\u5728\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 </html> NameSearchPanel.noteNameLabel.text=<html>*\u6CE8\u610F\uFF1A\u540D\u524D\u30DE\u30C3\u30C1\u306F\u5927\u6587\u5B57\u3068\u5C0F\u6587\u5B57\u3092\u533A\u5225\u3057\u307E\u3059\u3002\u307E\u305F\u3001<br/> \u30D5\u30A1\u30A4\u30EB\u540D\u306E\u3044\u304B\u306A\u308B\u90E8\u5206\u3082\u30DE\u30C3\u30C1\u3057\u307E\u3059\u3002\u6B63\u898F\u8868\u73FE\u306F<br/>\u73FE\u5728\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002 </html>
SizeSearchPanel.sizeCheckBox.text=\u30B5\u30A4\u30BA\uFF1A SizeSearchPanel.sizeCheckBox.text=\u30B5\u30A4\u30BA\uFF1A
NameSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8 NameSearchPanel.cutMenuItem.text=\u30AB\u30C3\u30C8
NameSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC NameSearchPanel.copyMenuItem.text=\u30B3\u30D4\u30FC
@ -32,7 +32,7 @@ FileSearchAction.getName.text=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u
FileSearchDialog.frame.title=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 FileSearchDialog.frame.title=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22
FileSearchDialog.frame.msg=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22 FileSearchDialog.frame.msg=\u5C5E\u6027\u306B\u3088\u308B\u30D5\u30A1\u30A4\u30EB\u691C\u7D22
FileSearchPanel.custComp.label.text=\u4E0B\u8A18\u306E\u6761\u4EF6\u306B\u4E00\u81F4\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\uFF1A FileSearchPanel.custComp.label.text=\u4E0B\u8A18\u306E\u6761\u4EF6\u306B\u4E00\u81F4\u3059\u308B\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\uFF1A
FileSearchPanel.filterTitle.name=\u540D\u79F0 FileSearchPanel.filterTitle.name=\u540D\u524D
FileSearchPanel.filterTitle.metadata=\u30E1\u30BF\u30C7\u30FC\u30BF FileSearchPanel.filterTitle.metadata=\u30E1\u30BF\u30C7\u30FC\u30BF
FileSearchPanel.filterTitle.knownStatus=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9 FileSearchPanel.filterTitle.knownStatus=\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9
FileSearchPanel.searchButton.text=\u691C\u7D22 FileSearchPanel.searchButton.text=\u691C\u7D22
@ -43,5 +43,5 @@ FileSearchPanel.search.results.details=\u591A\u304F\u306E\u30DE\u30C3\u30C1\u304
FileSearchPanel.search.exception.noFilterSelected.msg=\u6700\u4F4E\uFF11\u500B\u306E\u30D5\u30A3\u30EB\u30BF\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 FileSearchPanel.search.exception.noFilterSelected.msg=\u6700\u4F4E\uFF11\u500B\u306E\u30D5\u30A3\u30EB\u30BF\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002
FileSearchPanel.search.validationErr.msg=\u30D0\u30EA\u30C7\u30FC\u30B7\u30E7\u30F3\u30A8\u30E9\u30FC\uFF1A{0} FileSearchPanel.search.validationErr.msg=\u30D0\u30EA\u30C7\u30FC\u30B7\u30E7\u30F3\u30A8\u30E9\u30FC\uFF1A{0}
KnownStatusSearchFilter.noneSelectedMsg.text=\u6700\u4F4E\uFF11\u500B\u306E\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF01 KnownStatusSearchFilter.noneSelectedMsg.text=\u6700\u4F4E\uFF11\u500B\u306E\u65E2\u77E5\u30B9\u30C6\u30FC\u30BF\u30B9\u3092\u9078\u629E\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF01
NameSearchFilter.emptyNameMsg.text=\u540D\u79F0\u691C\u7D22\u306B\u4F55\u304B\u8A18\u5165\u3057\u306A\u3051\u308C\u3070\u3044\u3051\u307E\u305B\u3093\u3002 NameSearchFilter.emptyNameMsg.text=\u540D\u524D\u691C\u7D22\u306B\u4F55\u304B\u8A18\u5165\u3057\u306A\u3051\u308C\u3070\u3044\u3051\u307E\u305B\u3093\u3002
SearchNode.getName.text=\u691C\u7D22\u7D50\u679C SearchNode.getName.text=\u691C\u7D22\u7D50\u679C

View File

@ -16,9 +16,11 @@ IngestMessagePanel.totalMessagesNameLabel.text=Total:
IngestMessagePanel.totalMessagesNameVal.text=- IngestMessagePanel.totalMessagesNameVal.text=-
IngestMessagePanel.totalUniqueMessagesNameLabel.text=Unique: IngestMessagePanel.totalUniqueMessagesNameLabel.text=Unique:
IngestMessagePanel.totalUniqueMessagesNameVal.text=- IngestMessagePanel.totalUniqueMessagesNameVal.text=-
IngestJob.progress.dataSourceIngest.displayName=Data Source Ingest of {0}
IngestJob.progress.fileIngest.displayName=File Ingest of {0}
IngestJob.progress.cancelling={0} (Cancelling...)
IngestJobConfigurationPanel.processUnallocCheckbox.toolTipText=Processes unallocated space, such as deleted files. Produces more complete results, but it may take longer to process on large images. IngestJobConfigurationPanel.processUnallocCheckbox.toolTipText=Processes unallocated space, such as deleted files. Produces more complete results, but it may take longer to process on large images.
IngestJobConfigurationPanel.processUnallocCheckbox.text=Process Unallocated Space IngestJobConfigurationPanel.processUnallocCheckbox.text=Process Unallocated Space
IngestJobConfigurationPanel.advancedButton.text=Advanced
IngestJob.toString.text=ScheduledTask'{'input\={0}, modules\={1}'}' IngestJob.toString.text=ScheduledTask'{'input\={0}, modules\={1}'}'
IngestJobLauncher.modName.tbirdParser.text=Thunderbird Parser IngestJobLauncher.modName.tbirdParser.text=Thunderbird Parser
IngestJobLauncher.modName.mboxParser.text=MBox Parser IngestJobLauncher.modName.mboxParser.text=MBox Parser
@ -46,14 +48,8 @@ IngestManager.toHtmlStr.totalErrs.text=Total errors\: {0}
IngestManager.toHtmlStr.module.text=Module IngestManager.toHtmlStr.module.text=Module
IngestManager.toHtmlStr.time.text=Time IngestManager.toHtmlStr.time.text=Time
IngestManager.toHtmlStr.errors.text=Errors IngestManager.toHtmlStr.errors.text=Errors
IngestManager.FileTaskWorker.displayName=File Ingest
IngestManager.FileTaskWorker.process.cancelling={0} (Cancelling...)
IngestManager.EnqueueWorker.displayName.text=Queueing Ingest IngestManager.EnqueueWorker.displayName.text=Queueing Ingest
IngestManager.EnqueueWorker.process.cancelling={0} (Cancelling...) IngestManager.EnqueueWorker.process.cancelling={0} (Cancelling...)
IngestManager.DataSourceTaskWorker.progress.pending={0} (Pending...)
IngestManager.DataSourceTaskWorker.progress.cancelling={0} (Cancelling...)
IngestManager.datatSourceIngest.progress.text=DataSource Ingest {0}
IngestManager.fileIngest.progress.text=File Ingest {0}
IngestJob.DataSourceIngestPipeline.displayName.text={0} processing {1} IngestJob.DataSourceIngestPipeline.displayName.text={0} processing {1}
IngestMessage.toString.type.text=type\: {0} IngestMessage.toString.type.text=type\: {0}
IngestMessage.toString.source.text=\ source\: {0} IngestMessage.toString.source.text=\ source\: {0}
@ -101,3 +97,6 @@ IngestScheduler.remove.exception.notSupported.msg=Not supported.
IngestScheduler.DataSourceScheduler.exception.next.msg=There is no data source tasks in the queue, check hasNext() IngestScheduler.DataSourceScheduler.exception.next.msg=There is no data source tasks in the queue, check hasNext()
IngestScheduler.DataSourceScheduler.exception.remove.msg=Removing of scheduled data source ingest tasks is not supported. IngestScheduler.DataSourceScheduler.exception.remove.msg=Removing of scheduled data source ingest tasks is not supported.
IngestScheduler.DataSourceScheduler.toString.size=DataSourceQueue, size\: {0} IngestScheduler.DataSourceScheduler.toString.size=DataSourceQueue, size\: {0}
Label1
IngestJobConfigurationPanel.advancedButton.text=Advanced
IngestJobConfigurationPanel.advancedButton.actionCommand=Advanced

View File

@ -22,16 +22,18 @@ import org.sleuthkit.datamodel.Content;
/** /**
* Interface that must be implemented by all data source ingest modules. * Interface that must be implemented by all data source ingest modules.
* See description of IngestModule for more details on interface behavior.
*/ */
public interface DataSourceIngestModule extends IngestModule { public interface DataSourceIngestModule extends IngestModule {
/** /**
* Processes a data source. * Processes a data source. Called once between calls to startUp()
* and shutDown().
* *
* @param dataSource The data source to process. * @param dataSource The data source to process.
* @param statusHelper A status helper to be used to report progress and * @param statusHelper A status helper to be used to report progress and
* detect ingest job cancellation. * detect ingest job cancellation.
* @return A result code indicating success or failure of the processing. * @return A result code indicating success or failure of the processing.
*/ */
ProcessResult process(Content dataSource, DataSourceIngestModuleStatusHelper statusHelper); ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper);
} }

View File

@ -18,35 +18,17 @@
*/ */
package org.sleuthkit.autopsy.ingest; package org.sleuthkit.autopsy.ingest;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle;
import org.sleuthkit.datamodel.Content;
/** /**
* Used by data source ingest modules to report progress and detect data source * Used by data source ingest modules to report progress.
* ingest job cancellation.
*/ */
public class DataSourceIngestModuleStatusHelper { public class DataSourceIngestModuleProgress {
private final SwingWorker worker; private final IngestJob ingestJob;
private final ProgressHandle progress; private final String moduleDisplayName;
private final Content dataSource;
DataSourceIngestModuleStatusHelper(SwingWorker worker, ProgressHandle progress, Content dataSource) { DataSourceIngestModuleProgress(IngestJob ingestJob, String moduleDisplayName) {
this.worker = worker; this.ingestJob = ingestJob;
this.progress = progress; this.moduleDisplayName = moduleDisplayName;
this.dataSource = dataSource;
}
/**
* Checks for ingest job cancellation. This should be polled by the module
* in its process() method. If the ingest task is canceled, the module
* should return from its process() method as quickly as possible.
*
* @return True if the task has been canceled, false otherwise.
*/
public boolean isCancelled() {
return worker.isCancelled();
} }
/** /**
@ -58,9 +40,7 @@ public class DataSourceIngestModuleStatusHelper {
* data source. * data source.
*/ */
public void switchToDeterminate(int workUnits) { public void switchToDeterminate(int workUnits) {
if (progress != null) { ingestJob.getDataSourceTaskProgressBar().switchToDeterminate(workUnits);
progress.switchToDeterminate(workUnits);
}
} }
/** /**
@ -68,9 +48,7 @@ public class DataSourceIngestModuleStatusHelper {
* the total work units to process the data source is unknown. * the total work units to process the data source is unknown.
*/ */
public void switchToIndeterminate() { public void switchToIndeterminate() {
if (progress != null) { ingestJob.getDataSourceTaskProgressBar().switchToIndeterminate();
progress.switchToIndeterminate();
}
} }
/** /**
@ -80,8 +58,6 @@ public class DataSourceIngestModuleStatusHelper {
* @param workUnits Number of work units performed so far by the module. * @param workUnits Number of work units performed so far by the module.
*/ */
public void progress(int workUnits) { public void progress(int workUnits) {
if (progress != null) { ingestJob.getDataSourceTaskProgressBar().progress(this.moduleDisplayName, workUnits);
progress.progress(dataSource.getName(), workUnits);
}
} }
} }

View File

@ -0,0 +1,138 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 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.ingest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sleuthkit.datamodel.Content;
/**
* A data source ingest pipeline composed of a sequence of data source ingest
* modules constructed from ingest module templates.
*/
final class DataSourceIngestPipeline {
private final IngestJob job;
private final List<IngestModuleTemplate> moduleTemplates;
private List<DataSourceIngestModuleDecorator> modules = new ArrayList<>();
DataSourceIngestPipeline(IngestJob task, List<IngestModuleTemplate> moduleTemplates) {
this.job = task;
this.moduleTemplates = moduleTemplates;
}
List<IngestModuleError> startUp() {
List<IngestModuleError> errors = new ArrayList<>();
// Create an ingest module instance from each ingest module template
// that has an ingest module factory capable of making data source
// ingest modules. Map the module class names to the module instance
// to allow the modules to be put in the sequence indicated by the
// ingest pipelines configuration.
Map<String, DataSourceIngestModuleDecorator> modulesByClass = new HashMap<>();
for (IngestModuleTemplate template : moduleTemplates) {
if (template.isDataSourceIngestModuleTemplate()) {
DataSourceIngestModuleDecorator module = new DataSourceIngestModuleDecorator(template.createDataSourceIngestModule(), template.getModuleName());
IngestJobContext context = new IngestJobContext(job);
try {
module.startUp(context);
modulesByClass.put(module.getClassName(), module);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
}
}
// Establish the module sequence of the core ingest modules
// indicated by the ingest pipeline configuration, adding any
// additional modules found in the global lookup to the end of the
// pipeline in arbitrary order.
List<String> pipelineConfig = IngestPipelinesConfiguration.getInstance().getDataSourceIngestPipelineConfig();
for (String moduleClassName : pipelineConfig) {
if (modulesByClass.containsKey(moduleClassName)) {
modules.add(modulesByClass.remove(moduleClassName));
}
}
for (DataSourceIngestModuleDecorator module : modulesByClass.values()) {
modules.add(module);
}
return errors;
}
List<IngestModuleError> process() {
List<IngestModuleError> errors = new ArrayList<>();
for (DataSourceIngestModuleDecorator module : this.modules) {
try {
module.process(job.getDataSource(), new DataSourceIngestModuleProgress(job, module.getDisplayName()));
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
if (job.isCancelled()) {
break;
}
}
return errors;
}
List<IngestModuleError> shutDown(boolean ingestJobCancelled) {
List<IngestModuleError> errors = new ArrayList<>();
for (DataSourceIngestModuleDecorator module : this.modules) {
try {
module.shutDown(ingestJobCancelled);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
}
return errors;
}
private static class DataSourceIngestModuleDecorator implements DataSourceIngestModule {
private final DataSourceIngestModule module;
private final String displayName;
DataSourceIngestModuleDecorator(DataSourceIngestModule module, String displayName) {
this.module = module;
this.displayName = displayName;
}
String getClassName() {
return module.getClass().getCanonicalName();
}
String getDisplayName() {
return displayName;
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
module.startUp(context);
}
@Override
public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
return module.process(dataSource, statusHelper);
}
@Override
public void shutDown(boolean ingestJobWasCancelled) {
module.shutDown(ingestJobWasCancelled);
}
}
}

View File

@ -22,13 +22,15 @@ import org.sleuthkit.datamodel.AbstractFile;
/** /**
* Interface that must be implemented by all file ingest modules. * Interface that must be implemented by all file ingest modules.
* See description of IngestModule for more details on interface behavior.
*/ */
public interface FileIngestModule extends IngestModule { public interface FileIngestModule extends IngestModule {
/** /**
* Processes a file. * Processes a file. Called between calls to startUp() and shutDown().
* Will be called for each file in a data source.
* *
* @param file The file. * @param file The file to analyze.
* @return A result code indicating success or failure of the processing. * @return A result code indicating success or failure of the processing.
*/ */
ProcessResult process(AbstractFile file); ProcessResult process(AbstractFile file);

View File

@ -0,0 +1,142 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 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.ingest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.sleuthkit.datamodel.AbstractFile;
/**
* A file ingest pipeline composed of a sequence of file ingest modules
* constructed from ingest module templates.
*/
final class FileIngestPipeline {
private final IngestJob job;
private final List<IngestModuleTemplate> moduleTemplates;
private List<FileIngestModuleDecorator> modules = new ArrayList<>();
FileIngestPipeline(IngestJob task, List<IngestModuleTemplate> moduleTemplates) {
this.job = task;
this.moduleTemplates = moduleTemplates;
}
List<IngestModuleError> startUp() {
List<IngestModuleError> errors = new ArrayList<>();
// Create an ingest module instance from each ingest module template
// that has an ingest module factory capable of making data source
// ingest modules. Map the module class names to the module instance
// to allow the modules to be put in the sequence indicated by the
// ingest pipelines configuration.
Map<String, FileIngestModuleDecorator> modulesByClass = new HashMap<>();
for (IngestModuleTemplate template : moduleTemplates) {
if (template.isFileIngestModuleTemplate()) {
FileIngestModuleDecorator module = new FileIngestModuleDecorator(template.createFileIngestModule(), template.getModuleName());
IngestJobContext context = new IngestJobContext(job);
try {
module.startUp(context);
modulesByClass.put(module.getClassName(), module);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
}
}
// Establish the module sequence of the core ingest modules
// indicated by the ingest pipeline configuration, adding any
// additional modules found in the global lookup to the end of the
// pipeline in arbitrary order.
List<String> pipelineConfig = IngestPipelinesConfiguration.getInstance().getFileIngestPipelineConfig();
for (String moduleClassName : pipelineConfig) {
if (modulesByClass.containsKey(moduleClassName)) {
modules.add(modulesByClass.remove(moduleClassName));
}
}
for (FileIngestModuleDecorator module : modulesByClass.values()) {
modules.add(module);
}
return errors;
}
List<IngestModuleError> process(AbstractFile file) {
List<IngestModuleError> errors = new ArrayList<>();
for (FileIngestModuleDecorator module : this.modules) {
try {
module.process(file);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
if (job.isCancelled()) {
break;
}
}
file.close();
if (!job.isCancelled()) {
IngestManager.fireFileIngestDone(file.getId());
}
return errors;
}
List<IngestModuleError> shutDown(boolean ingestJobCancelled) {
List<IngestModuleError> errors = new ArrayList<>();
for (FileIngestModuleDecorator module : this.modules) {
try {
module.shutDown(ingestJobCancelled);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
}
return errors;
}
private static class FileIngestModuleDecorator implements FileIngestModule {
private final FileIngestModule module;
private final String displayName;
FileIngestModuleDecorator(FileIngestModule module, String displayName) {
this.module = module;
this.displayName = displayName;
}
String getClassName() {
return module.getClass().getCanonicalName();
}
String getDisplayName() {
return displayName;
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
module.startUp(context);
}
@Override
public IngestModule.ProcessResult process(AbstractFile file) {
return module.process(file);
}
@Override
public void shutDown(boolean ingestJobWasCancelled) {
module.shutDown(ingestJobWasCancelled);
}
}
}

View File

@ -21,13 +21,10 @@ package org.sleuthkit.autopsy.ingest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Cancellable;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
/** /**
@ -42,9 +39,14 @@ final class IngestJob {
private final boolean processUnallocatedSpace; private final boolean processUnallocatedSpace;
private final HashMap<Long, FileIngestPipeline> fileIngestPipelines = new HashMap<>(); private final HashMap<Long, FileIngestPipeline> fileIngestPipelines = new HashMap<>();
private final HashMap<Long, DataSourceIngestPipeline> dataSourceIngestPipelines = new HashMap<>(); private final HashMap<Long, DataSourceIngestPipeline> dataSourceIngestPipelines = new HashMap<>();
private final IngestScheduler.FileScheduler fileScheduler = IngestScheduler.getInstance().getFileScheduler();
private FileIngestPipeline initialFileIngestPipeline = null; private FileIngestPipeline initialFileIngestPipeline = null;
private DataSourceIngestPipeline initialDataSourceIngestPipeline = null; private DataSourceIngestPipeline initialDataSourceIngestPipeline = null;
private boolean cancelled; private ProgressHandle dataSourceTaskProgress;
private ProgressHandle fileTasksProgress;
int totalEnqueuedFiles = 0;
private int processedFiles = 0;
private volatile boolean cancelled;
IngestJob(long id, Content dataSource, List<IngestModuleTemplate> ingestModuleTemplates, boolean processUnallocatedSpace) { IngestJob(long id, Content dataSource, List<IngestModuleTemplate> ingestModuleTemplates, boolean processUnallocatedSpace) {
this.id = id; this.id = id;
@ -66,15 +68,53 @@ final class IngestJob {
return processUnallocatedSpace; return processUnallocatedSpace;
} }
synchronized void cancel() {
cancelled = true;
}
synchronized boolean isCancelled() {
return cancelled;
}
synchronized List<IngestModuleError> startUpIngestPipelines() { synchronized List<IngestModuleError> startUpIngestPipelines() {
startDataSourceIngestProgressBar();
startFileIngestProgressBar();
return startUpInitialIngestPipelines();
}
private void startDataSourceIngestProgressBar() {
final String displayName = NbBundle
.getMessage(this.getClass(), "IngestJob.progress.dataSourceIngest.displayName", this.dataSource.getName());
dataSourceTaskProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
@Override
public boolean cancel() {
if (dataSourceTaskProgress != null) {
dataSourceTaskProgress.setDisplayName(NbBundle.getMessage(this.getClass(),
"IngestJob.progress.cancelling",
displayName));
}
IngestManager.getInstance().cancelIngestJobs();
return true;
}
});
dataSourceTaskProgress.start();
dataSourceTaskProgress.switchToIndeterminate();
}
private void startFileIngestProgressBar() {
final String displayName = NbBundle
.getMessage(this.getClass(), "IngestJob.progress.fileIngest.displayName", this.dataSource.getName());
fileTasksProgress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
@Override
public boolean cancel() {
if (fileTasksProgress != null) {
fileTasksProgress.setDisplayName(
NbBundle.getMessage(this.getClass(), "IngestJob.progress.cancelling",
displayName));
}
IngestManager.getInstance().cancelIngestJobs();
return true;
}
});
fileTasksProgress.start();
fileTasksProgress.switchToIndeterminate();
totalEnqueuedFiles = fileScheduler.getFilesEnqueuedEst();
fileTasksProgress.switchToDeterminate(totalEnqueuedFiles);
}
private List<IngestModuleError> startUpInitialIngestPipelines() {
// Create a per thread instance of each pipeline type right now to make // Create a per thread instance of each pipeline type right now to make
// (reasonably) sure that the ingest modules can be started. // (reasonably) sure that the ingest modules can be started.
initialDataSourceIngestPipeline = new DataSourceIngestPipeline(this, ingestModuleTemplates); initialDataSourceIngestPipeline = new DataSourceIngestPipeline(this, ingestModuleTemplates);
@ -123,267 +163,65 @@ final class IngestJob {
DataSourceIngestPipeline dataSourceIngestPipeline = dataSourceIngestPipelines.get(threadId); DataSourceIngestPipeline dataSourceIngestPipeline = dataSourceIngestPipelines.get(threadId);
if (dataSourceIngestPipeline != null) { if (dataSourceIngestPipeline != null) {
errors.addAll(dataSourceIngestPipeline.shutDown(cancelled)); errors.addAll(dataSourceIngestPipeline.shutDown(cancelled));
dataSourceIngestPipelines.remove(threadId);
}
if (initialDataSourceIngestPipeline == null && dataSourceIngestPipelines.isEmpty() && dataSourceTaskProgress != null) {
dataSourceTaskProgress.finish();
dataSourceTaskProgress = null;
} }
this.dataSourceIngestPipelines.remove(threadId);
FileIngestPipeline fileIngestPipeline = fileIngestPipelines.get(threadId); FileIngestPipeline fileIngestPipeline = fileIngestPipelines.get(threadId);
if (fileIngestPipeline != null) { if (fileIngestPipeline != null) {
errors.addAll(fileIngestPipeline.shutDown(cancelled)); errors.addAll(fileIngestPipeline.shutDown(cancelled));
fileIngestPipelines.remove(threadId);
}
if (initialFileIngestPipeline == null && fileIngestPipelines.isEmpty() && fileTasksProgress != null) {
fileTasksProgress.finish();
fileTasksProgress = null;
} }
this.fileIngestPipelines.remove(threadId);
return errors; return errors;
} }
synchronized boolean areIngestPipelinesShutDown() { synchronized boolean areIngestPipelinesShutDown() {
return (dataSourceIngestPipelines.isEmpty() && fileIngestPipelines.isEmpty()); return (initialDataSourceIngestPipeline == null
&& dataSourceIngestPipelines.isEmpty()
&& initialFileIngestPipeline == null
&& fileIngestPipelines.isEmpty());
} }
/** synchronized ProgressHandle getDataSourceTaskProgressBar() {
* A data source ingest pipeline composed of a sequence of data source ingest return this.dataSourceTaskProgress;
* modules constructed from ingest module templates.
*/
static final class DataSourceIngestPipeline {
private static final Logger logger = Logger.getLogger(DataSourceIngestPipeline.class.getName());
private final IngestJob task;
private final List<IngestModuleTemplate> moduleTemplates;
private List<DataSourceIngestModuleDecorator> modules = new ArrayList<>();
private DataSourceIngestPipeline(IngestJob task, List<IngestModuleTemplate> moduleTemplates) {
this.task = task;
this.moduleTemplates = moduleTemplates;
}
private List<IngestModuleError> startUp() {
List<IngestModuleError> errors = new ArrayList<>();
// Create an ingest module instance from each ingest module template
// that has an ingest module factory capable of making data source
// ingest modules. Map the module class names to the module instance
// to allow the modules to be put in the sequence indicated by the
// ingest pipelines configuration.
Map<String, DataSourceIngestModuleDecorator> modulesByClass = new HashMap<>();
for (IngestModuleTemplate template : moduleTemplates) {
if (template.isDataSourceIngestModuleTemplate()) {
DataSourceIngestModuleDecorator module = new DataSourceIngestModuleDecorator(template.createDataSourceIngestModule(), template.getModuleName());
IngestJobContext context = new IngestJobContext(task);
try {
module.startUp(context);
modulesByClass.put(module.getClassName(), module);
IngestManager.fireModuleEvent(IngestManager.IngestEvent.STARTED.toString(), module.getDisplayName());
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
}
}
// Establish the module sequence of the core ingest modules
// indicated by the ingest pipeline configuration, adding any
// additional modules found in the global lookup to the end of the
// pipeline in arbitrary order.
List<String> pipelineConfig = IngestPipelinesConfiguration.getInstance().getDataSourceIngestPipelineConfig();
for (String moduleClassName : pipelineConfig) {
if (modulesByClass.containsKey(moduleClassName)) {
modules.add(modulesByClass.remove(moduleClassName));
}
}
for (DataSourceIngestModuleDecorator module : modulesByClass.values()) {
modules.add(module);
}
return errors;
}
List<IngestModuleError> process(SwingWorker worker, ProgressHandle progress) {
List<IngestModuleError> errors = new ArrayList<>();
Content dataSource = this.task.getDataSource();
logger.log(Level.INFO, "Processing data source {0}", dataSource.getName());
for (DataSourceIngestModuleDecorator module : this.modules) {
try {
String displayName = NbBundle.getMessage(this.getClass(), "IngestJob.DataSourceIngestPipeline.displayName.text", module.getDisplayName(), dataSource.getName());
progress.setDisplayName(displayName);
module.process(dataSource, new DataSourceIngestModuleStatusHelper(worker, progress, dataSource));
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
if (task.isCancelled()) {
break;
}
}
return errors;
}
private List<IngestModuleError> shutDown(boolean ingestJobCancelled) {
List<IngestModuleError> errors = new ArrayList<>();
for (DataSourceIngestModuleDecorator module : this.modules) {
try {
module.shutDown(ingestJobCancelled);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
} finally {
IngestManager.fireModuleEvent(IngestManager.IngestEvent.COMPLETED.toString(), module.getDisplayName());
}
}
return errors;
}
private static class DataSourceIngestModuleDecorator implements DataSourceIngestModule {
private final DataSourceIngestModule module;
private final String displayName;
DataSourceIngestModuleDecorator(DataSourceIngestModule module, String displayName) {
this.module = module;
this.displayName = displayName;
}
String getClassName() {
return module.getClass().getCanonicalName();
}
String getDisplayName() {
return displayName;
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
module.startUp(context);
}
@Override
public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleStatusHelper statusHelper) {
return module.process(dataSource, statusHelper);
}
@Override
public void shutDown(boolean ingestJobWasCancelled) {
module.shutDown(ingestJobWasCancelled);
}
}
} }
/** synchronized void updateFileTasksProgressBar(String currentFileName) {
* A file ingest pipeline composed of a sequence of file ingest modules int newTotalEnqueuedFiles = fileScheduler.getFilesEnqueuedEst();
* constructed from ingest module templates. if (newTotalEnqueuedFiles > totalEnqueuedFiles) {
*/ totalEnqueuedFiles = newTotalEnqueuedFiles + 1;
static final class FileIngestPipeline { fileTasksProgress.switchToIndeterminate();
fileTasksProgress.switchToDeterminate(totalEnqueuedFiles);
private static final Logger logger = Logger.getLogger(FileIngestPipeline.class.getName()); }
private final IngestJob task; if (processedFiles < totalEnqueuedFiles) {
private final List<IngestModuleTemplate> moduleTemplates; ++processedFiles;
private List<FileIngestModuleDecorator> modules = new ArrayList<>();
private FileIngestPipeline(IngestJob task, List<IngestModuleTemplate> moduleTemplates) {
this.task = task;
this.moduleTemplates = moduleTemplates;
} }
private List<IngestModuleError> startUp() { fileTasksProgress.progress(currentFileName, processedFiles);
List<IngestModuleError> errors = new ArrayList<>(); }
// Create an ingest module instance from each ingest module template synchronized void cancel() {
// that has an ingest module factory capable of making data source if (initialDataSourceIngestPipeline != null) {
// ingest modules. Map the module class names to the module instance initialDataSourceIngestPipeline.shutDown(true);
// to allow the modules to be put in the sequence indicated by the initialDataSourceIngestPipeline = null;
// ingest pipelines configuration. }
Map<String, FileIngestModuleDecorator> modulesByClass = new HashMap<>(); if (initialFileIngestPipeline != null) {
for (IngestModuleTemplate template : moduleTemplates) { initialFileIngestPipeline.shutDown(true);
if (template.isFileIngestModuleTemplate()) { initialFileIngestPipeline = null;
FileIngestModuleDecorator module = new FileIngestModuleDecorator(template.createFileIngestModule(), template.getModuleName());
IngestJobContext context = new IngestJobContext(task);
try {
module.startUp(context);
modulesByClass.put(module.getClassName(), module);
IngestManager.fireModuleEvent(IngestManager.IngestEvent.STARTED.toString(), template.getModuleName());
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
}
}
// Establish the module sequence of the core ingest modules
// indicated by the ingest pipeline configuration, adding any
// additional modules found in the global lookup to the end of the
// pipeline in arbitrary order.
List<String> pipelineConfig = IngestPipelinesConfiguration.getInstance().getFileIngestPipelineConfig();
for (String moduleClassName : pipelineConfig) {
if (modulesByClass.containsKey(moduleClassName)) {
modules.add(modulesByClass.remove(moduleClassName));
}
}
for (FileIngestModuleDecorator module : modulesByClass.values()) {
modules.add(module);
}
return errors;
} }
List<IngestModuleError> process(AbstractFile file) { cancelled = true;
List<IngestModuleError> errors = new ArrayList<>(); }
Content dataSource = this.task.getDataSource();
logger.log(Level.INFO, String.format("Processing {0} from {1}", file.getName(), dataSource.getName()));
for (FileIngestModuleDecorator module : this.modules) {
try {
module.process(file);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
}
if (task.isCancelled()) {
break;
}
}
file.close();
IngestManager.fireFileDone(file.getId());
return errors;
}
private List<IngestModuleError> shutDown(boolean ingestJobCancelled) { boolean isCancelled() {
List<IngestModuleError> errors = new ArrayList<>(); return cancelled;
for (FileIngestModuleDecorator module : this.modules) {
try {
module.shutDown(ingestJobCancelled);
} catch (Exception ex) {
errors.add(new IngestModuleError(module.getDisplayName(), ex));
} finally {
IngestManager.fireModuleEvent(IngestManager.IngestEvent.COMPLETED.toString(), module.getDisplayName());
}
}
return errors;
}
private static class FileIngestModuleDecorator implements FileIngestModule {
private final FileIngestModule module;
private final String displayName;
FileIngestModuleDecorator(FileIngestModule module, String displayName) {
this.module = module;
this.displayName = displayName;
}
String getClassName() {
return module.getClass().getCanonicalName();
}
String getDisplayName() {
return displayName;
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
module.startUp(context);
}
@Override
public IngestModule.ProcessResult process(AbstractFile file) {
return module.process(file);
}
@Override
public void shutDown(boolean ingestJobWasCancelled) {
module.shutDown(ingestJobWasCancelled);
}
}
} }
} }

View File

@ -13,7 +13,7 @@
<Dimension value="[522, 257]"/> <Dimension value="[522, 257]"/>
</Property> </Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[575, 300]"/> <Dimension value="[575, 400]"/>
</Property> </Property>
</Properties> </Properties>
<AuxValues> <AuxValues>
@ -48,9 +48,9 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" pref="278" max="32767" attributes="0"/> <Component id="jPanel1" pref="342" max="32767" attributes="0"/>
<Group type="102" attributes="0"> <Group type="102" attributes="0">
<Component id="modulesScrollPane" pref="233" max="32767" attributes="0"/> <Component id="modulesScrollPane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="processUnallocPanel" max="-2" attributes="0"/> <Component id="processUnallocPanel" max="-2" attributes="0"/>
</Group> </Group>
@ -108,24 +108,40 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="326" max="32767" attributes="0"/> <Group type="102" attributes="0">
<Component id="jSeparator2" alignment="1" max="32767" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Group type="102" alignment="1" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<EmptySpace max="32767" attributes="0"/> <Component id="jScrollPane1" pref="316" max="32767" attributes="0"/>
<Component id="advancedButton" min="-2" max="-2" attributes="0"/> <Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/> <Component id="scrollpane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="advancedButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="14" max="-2" attributes="0"/>
</Group>
</Group>
</Group> </Group>
<Component id="jSeparator2" max="32767" attributes="0"/>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0"> <Group type="102" alignment="1" attributes="0">
<Component id="jScrollPane1" max="32767" attributes="0"/> <Component id="jScrollPane1" pref="242" max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="22" max="-2" attributes="0"/>
<Component id="scrollpane" min="-2" pref="65" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="advancedButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jSeparator2" min="-2" pref="10" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="advancedButton" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -136,6 +152,9 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobConfigurationPanel.advancedButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobConfigurationPanel.advancedButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="actionCommand" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/ingest/Bundle.properties" key="IngestJobConfigurationPanel.advancedButton.actionCommand" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
</Properties> </Properties>
<Events> <Events>
@ -164,6 +183,40 @@
</Container> </Container>
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JScrollPane" name="scrollpane">
<Properties>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="horizontalScrollBarPolicy" type="int" value="31"/>
<Property name="verticalScrollBarPolicy" type="int" value="21"/>
</Properties>
<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="descriptionLabel">
<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="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents> </SubComponents>
</Container> </Container>
<Container class="javax.swing.JPanel" name="processUnallocPanel"> <Container class="javax.swing.JPanel" name="processUnallocPanel">
@ -183,7 +236,7 @@
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="processUnallocCheckbox" min="-2" max="-2" attributes="0"/> <Component id="processUnallocCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="60" max="32767" attributes="0"/> <EmptySpace pref="108" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>

View File

@ -107,6 +107,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
simplePanel.revalidate(); simplePanel.revalidate();
simplePanel.repaint(); simplePanel.repaint();
advancedButton.setEnabled(null != selectedModule.getGlobalSettingsPanel()); advancedButton.setEnabled(null != selectedModule.getGlobalSettingsPanel());
descriptionLabel.setText(selectedModule.getDescription());
} }
} }
}); });
@ -131,12 +132,14 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
jSeparator2 = new javax.swing.JSeparator(); jSeparator2 = new javax.swing.JSeparator();
jScrollPane1 = new javax.swing.JScrollPane(); jScrollPane1 = new javax.swing.JScrollPane();
simplePanel = new javax.swing.JPanel(); simplePanel = new javax.swing.JPanel();
scrollpane = new javax.swing.JScrollPane();
descriptionLabel = new javax.swing.JTextArea();
processUnallocPanel = new javax.swing.JPanel(); processUnallocPanel = new javax.swing.JPanel();
processUnallocCheckbox = new javax.swing.JCheckBox(); processUnallocCheckbox = new javax.swing.JCheckBox();
setMaximumSize(new java.awt.Dimension(5750, 3000)); setMaximumSize(new java.awt.Dimension(5750, 3000));
setMinimumSize(new java.awt.Dimension(522, 257)); setMinimumSize(new java.awt.Dimension(522, 257));
setPreferredSize(new java.awt.Dimension(575, 300)); setPreferredSize(new java.awt.Dimension(575, 400));
modulesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160))); modulesScrollPane.setBorder(javax.swing.BorderFactory.createLineBorder(new java.awt.Color(160, 160, 160)));
modulesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160)); modulesScrollPane.setPreferredSize(new java.awt.Dimension(160, 160));
@ -158,6 +161,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
jPanel1.setPreferredSize(new java.awt.Dimension(338, 257)); jPanel1.setPreferredSize(new java.awt.Dimension(338, 257));
advancedButton.setText(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.advancedButton.text")); // NOI18N advancedButton.setText(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.advancedButton.text")); // NOI18N
advancedButton.setActionCommand(org.openide.util.NbBundle.getMessage(IngestJobConfigurationPanel.class, "IngestJobConfigurationPanel.advancedButton.actionCommand")); // NOI18N
advancedButton.setEnabled(false); advancedButton.setEnabled(false);
advancedButton.addActionListener(new java.awt.event.ActionListener() { advancedButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) { public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -171,25 +175,49 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
simplePanel.setLayout(new javax.swing.BoxLayout(simplePanel, javax.swing.BoxLayout.PAGE_AXIS)); simplePanel.setLayout(new javax.swing.BoxLayout(simplePanel, javax.swing.BoxLayout.PAGE_AXIS));
jScrollPane1.setViewportView(simplePanel); jScrollPane1.setViewportView(simplePanel);
scrollpane.setBorder(null);
scrollpane.setHorizontalScrollBarPolicy(javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
scrollpane.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
descriptionLabel.setEditable(false);
descriptionLabel.setBackground(new java.awt.Color(240, 240, 240));
descriptionLabel.setColumns(20);
descriptionLabel.setFont(new java.awt.Font("Tahoma", 0, 11)); // NOI18N
descriptionLabel.setLineWrap(true);
descriptionLabel.setRows(5);
descriptionLabel.setWrapStyleWord(true);
descriptionLabel.setBorder(null);
scrollpane.setViewportView(descriptionLabel);
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout); jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup( jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 326, Short.MAX_VALUE) .addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING) .addContainerGap()
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE)
.addComponent(advancedButton) .addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()) .addComponent(scrollpane)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(advancedButton)
.addGap(14, 14, 14))))
.addComponent(jSeparator2)
); );
jPanel1Layout.setVerticalGroup( jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup() .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 242, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE) .addGroup(jPanel1Layout.createSequentialGroup()
.addGap(0, 0, 0) .addGap(22, 22, 22)
.addComponent(advancedButton) .addComponent(scrollpane, javax.swing.GroupLayout.PREFERRED_SIZE, 65, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(advancedButton)))
.addContainerGap()) .addContainerGap())
); );
@ -210,7 +238,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
.addGroup(processUnallocPanelLayout.createSequentialGroup() .addGroup(processUnallocPanelLayout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addComponent(processUnallocCheckbox) .addComponent(processUnallocCheckbox)
.addContainerGap(60, Short.MAX_VALUE)) .addContainerGap(108, Short.MAX_VALUE))
); );
processUnallocPanelLayout.setVerticalGroup( processUnallocPanelLayout.setVerticalGroup(
processUnallocPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) processUnallocPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -238,15 +266,19 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE) .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 342, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 233, Short.MAX_VALUE) .addComponent(modulesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(processUnallocPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addComponent(processUnallocPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap()) .addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed
processUnallocatedSpace = processUnallocCheckbox.isSelected();
}//GEN-LAST:event_processUnallocCheckboxActionPerformed
private void advancedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedButtonActionPerformed private void advancedButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_advancedButtonActionPerformed
final AdvancedConfigurationDialog dialog = new AdvancedConfigurationDialog(); final AdvancedConfigurationDialog dialog = new AdvancedConfigurationDialog();
@ -270,11 +302,9 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
dialog.display(selectedModule.getGlobalSettingsPanel()); dialog.display(selectedModule.getGlobalSettingsPanel());
}//GEN-LAST:event_advancedButtonActionPerformed }//GEN-LAST:event_advancedButtonActionPerformed
private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed
processUnallocatedSpace = processUnallocCheckbox.isSelected();
}//GEN-LAST:event_processUnallocCheckboxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton advancedButton; private javax.swing.JButton advancedButton;
private javax.swing.JTextArea descriptionLabel;
private javax.swing.JPanel jPanel1; private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSeparator jSeparator2; private javax.swing.JSeparator jSeparator2;
@ -282,6 +312,7 @@ class IngestJobConfigurationPanel extends javax.swing.JPanel {
private javax.swing.JTable modulesTable; private javax.swing.JTable modulesTable;
private javax.swing.JCheckBox processUnallocCheckbox; private javax.swing.JCheckBox processUnallocCheckbox;
private javax.swing.JPanel processUnallocPanel; private javax.swing.JPanel processUnallocPanel;
private javax.swing.JScrollPane scrollpane;
private javax.swing.JPanel simplePanel; private javax.swing.JPanel simplePanel;
private javax.swing.ButtonGroup timeGroup; private javax.swing.ButtonGroup timeGroup;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables

View File

@ -58,9 +58,9 @@ public final class IngestJobContext {
* *
* @param files The files to be processed by the file ingest pipeline. * @param files The files to be processed by the file ingest pipeline.
*/ */
public void addFilesToPipeline(List<AbstractFile> files) { public void addFiles(List<AbstractFile> files) {
for (AbstractFile file : files) { for (AbstractFile file : files) {
IngestManager.getDefault().scheduleFile(ingestJob.getId(), file); IngestManager.getInstance().addFileToIngestJob(ingestJob.getId(), file);
} }
} }
} }

View File

@ -87,12 +87,12 @@ public final class IngestJobLauncher {
// NOTE: In the future, this code will be modified to get the // NOTE: In the future, this code will be modified to get the
// module settings for the current context, if available, from // module settings for the current context, if available, from
// storage; for now always use the defaults. // storage; for now always use the defaults.
IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, moduleFactory.getDefaultModuleSettings()); IngestModuleTemplate moduleTemplate = new IngestModuleTemplate(moduleFactory, moduleFactory.getDefaultIngestJobSettings());
String moduleName = moduleTemplate.getModuleName(); String moduleName = moduleTemplate.getModuleName();
if (enabledModuleNames.contains(moduleName)) { if (enabledModuleNames.contains(moduleName)) {
moduleTemplate.setEnabled(true); moduleTemplate.setEnabled(true);
} else if (disabledModuleNames.contains(moduleName)) { } else if (disabledModuleNames.contains(moduleName)) {
moduleTemplate.setEnabled(true); moduleTemplate.setEnabled(false);
} else { } else {
// The module factory was loaded, but the module name does not // The module factory was loaded, but the module name does not
// appear in the enabled/disabled module settings. Treat the // appear in the enabled/disabled module settings. Treat the
@ -232,7 +232,7 @@ public final class IngestJobLauncher {
} }
if ((!enabledModuleTemplates.isEmpty()) && (dataSources != null) && (!dataSources.isEmpty())) { if ((!enabledModuleTemplates.isEmpty()) && (dataSources != null) && (!dataSources.isEmpty())) {
IngestManager.getDefault().scheduleDataSourceTasks(dataSources, enabledModuleTemplates, ingestConfigPanel.getProcessUnallocSpace()); IngestManager.getInstance().startIngestJobs(dataSources, enabledModuleTemplates, ingestConfigPanel.getProcessUnallocSpace());
} }
} }
} }

View File

@ -24,65 +24,143 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.CancellationException; import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.netbeans.api.progress.ProgressHandleFactory; import org.netbeans.api.progress.ProgressHandleFactory;
import org.openide.util.Cancellable; import org.openide.util.Cancellable;
import org.openide.util.NbPreferences;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import java.util.prefs.Preferences;
import javax.swing.SwingWorker;
/** /**
* Manages the execution of ingest jobs. * Manages the execution of ingest jobs.
*/ */
public class IngestManager { public class IngestManager {
private static final String NUMBER_OF_FILE_INGEST_THREADS_KEY = "NumberOfFileingestThreads";
private static final int MIN_NUMBER_OF_FILE_INGEST_THREADS = 1;
private static final int MAX_NUMBER_OF_FILE_INGEST_THREADS = 4;
private static final int DEFAULT_NUMBER_OF_FILE_INGEST_THREADS = 2;
private static final Logger logger = Logger.getLogger(IngestManager.class.getName()); private static final Logger logger = Logger.getLogger(IngestManager.class.getName());
private static final PropertyChangeSupport pcs = new PropertyChangeSupport(IngestManager.class); private static final PropertyChangeSupport pcs = new PropertyChangeSupport(IngestManager.class);
private static final Preferences userPreferences = NbPreferences.forModule(IngestManager.class);
private static IngestManager instance; private static IngestManager instance;
private final IngestScheduler scheduler; private final IngestScheduler scheduler = IngestScheduler.getInstance();
private final IngestMonitor ingestMonitor = new IngestMonitor(); private final IngestMonitor ingestMonitor = new IngestMonitor();
private final HashMap<Long, IngestJob> ingestJobs = new HashMap<>(); private final ExecutorService startIngestJobsExecutor = Executors.newSingleThreadExecutor();
private TaskSchedulingWorker taskSchedulingWorker; private final ExecutorService dataSourceIngestTasksExecutor = Executors.newSingleThreadExecutor();
private FileTaskWorker fileTaskWorker; private final ExecutorService fileIngestTasksExecutor = Executors.newFixedThreadPool(MAX_NUMBER_OF_FILE_INGEST_THREADS);
private DataSourceTaskWorker dataSourceTaskWorker; private final HashMap<Long, IngestJob> ingestJobs = new HashMap<>(); // Maps job ids to jobs
private long nextDataSourceTaskId = 0; private final HashMap<Long, Future<?>> ingestTasks = new HashMap<>(); // Maps task ids to task cancellation handles
private long nextThreadId = 0; private AtomicLong ingestJobId = new AtomicLong(0L);
private AtomicLong ingestTaskId = new AtomicLong(0L);
private volatile IngestUI ingestMessageBox; private volatile IngestUI ingestMessageBox;
/**
* Gets the IngestManager singleton, creating it if necessary.
*
* @returns The IngestManager singleton.
*/
public synchronized static IngestManager getInstance() {
if (instance == null) {
instance = new IngestManager();
}
return instance;
}
private IngestManager() {
}
/**
* Finds the top component for the ingest messages in box. Called by the
* custom installer for this package once the window system is initialized.
*/
void initIngestMessageInbox() {
if (this.ingestMessageBox == null) {
this.ingestMessageBox = IngestMessageTopComponent.findInstance();
}
}
public synchronized static int getNumberOfFileIngestThreads() {
return userPreferences.getInt(NUMBER_OF_FILE_INGEST_THREADS_KEY, DEFAULT_NUMBER_OF_FILE_INGEST_THREADS);
}
public synchronized static void setNumberOfFileIngestThreads(int numberOfThreads) {
if (numberOfThreads < MIN_NUMBER_OF_FILE_INGEST_THREADS
|| numberOfThreads > MAX_NUMBER_OF_FILE_INGEST_THREADS) {
numberOfThreads = DEFAULT_NUMBER_OF_FILE_INGEST_THREADS;
}
userPreferences.putInt(NUMBER_OF_FILE_INGEST_THREADS_KEY, numberOfThreads);
}
synchronized void startIngestJobs(final List<Content> dataSources, final List<IngestModuleTemplate> moduleTemplates, boolean processUnallocatedSpace) {
if (!isIngestRunning() && ingestMessageBox != null) {
ingestMessageBox.clearMessages();
}
long taskId = ingestTaskId.incrementAndGet();
Future<?> task = startIngestJobsExecutor.submit(new StartIngestJobsTask(taskId, dataSources, moduleTemplates, processUnallocatedSpace));
ingestTasks.put(taskId, task);
if (ingestMessageBox != null) {
ingestMessageBox.restoreMessages();
}
}
/**
* Test if any ingest jobs are in progress.
*
* @return True if any ingest jobs are in progress, false otherwise
*/
public boolean isIngestRunning() {
return (ingestJobs.isEmpty() == false);
}
synchronized void addFileToIngestJob(long ingestJobId, AbstractFile file) {
IngestJob job = ingestJobs.get(ingestJobId);
if (job != null) {
scheduler.getFileScheduler().scheduleFile(job, file);
}
}
void cancelIngestJobs() {
new IngestCancellationWorker().execute();
}
/** /**
* Ingest events. * Ingest events.
*/ */
public enum IngestEvent { public enum IngestEvent {
// RJCTODO: Update comments
/** /**
* Event sent when an ingest module has been started. Second argument of * Property change event fired when an ingest job is started. The ingest
* the property change is a string form of the module name and the third * job id is in old value field of the PropertyChangeEvent object.
* argument is null.
*/ */
STARTED, INGEST_JOB_STARTED,
/** /**
* Event sent when an ingest module has completed processing by its own * Property change event fired when an ingest job is completed. The
* means. Second argument of the property change is a string form of the * ingest job id is in old value field of the PropertyChangeEvent
* module name and the third argument is null. * object.
*
* This event is generally used by listeners to perform a final data
* view refresh (listeners need to query all data from the blackboard).
*/ */
COMPLETED, INGEST_JOB_COMPLETED,
/** /**
* Event sent when an ingest module has stopped processing, and likely * Property change event fired when an ingest job is canceled. The
* not all data has been processed. Second argument of the property * ingest job id is in old value field of the PropertyChangeEvent
* change is a string form of the module name and third argument is * object.
* null.
*/ */
STOPPED, INGEST_JOB_CANCELLED,
/** /**
* Event sent when ingest module posts new data to blackboard or * Event sent when an ingest module posts new data to blackboard or
* somewhere else. Second argument of the property change fired contains * somewhere else. Second argument of the property change fired contains
* ModuleDataEvent object and third argument is null. The object can * ModuleDataEvent object and third argument is null. The object can
* contain encapsulated new data created by the module. Listener can * contain encapsulated new data created by the module. Listener can
@ -102,56 +180,22 @@ public class IngestManager {
FILE_DONE, FILE_DONE,
}; };
private IngestManager() {
this.scheduler = IngestScheduler.getInstance();
}
/** /**
* Returns reference to singleton instance. * Add property change listener to listen to ingest events.
*
* @returns Instance of class.
*/
synchronized public static IngestManager getDefault() {
if (instance == null) {
instance = new IngestManager();
}
return instance;
}
/**
* called by Installer in AWT thread once the Window System is ready
*/
void initIngestMessageInbox() {
if (this.ingestMessageBox == null) {
this.ingestMessageBox = IngestMessageTopComponent.findInstance();
}
}
synchronized private long getNextDataSourceTaskId() {
return ++this.nextDataSourceTaskId;
}
synchronized private long getNextThreadId() {
return ++this.nextThreadId;
}
/**
* Add property change listener to listen to ingest events as defined in
* IngestModuleEvent.
* *
* @param listener PropertyChangeListener to register * @param listener PropertyChangeListener to register
*/ */
public static synchronized void addPropertyChangeListener(final PropertyChangeListener listener) { public static void addPropertyChangeListener(final PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener); pcs.addPropertyChangeListener(listener);
} }
public static synchronized void removePropertyChangeListener(final PropertyChangeListener listener) { public static void removePropertyChangeListener(final PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener); pcs.removePropertyChangeListener(listener);
} }
static synchronized void fireModuleEvent(String eventType, String moduleName) { static void fireIngestJobEvent(String eventType, long jobId) {
try { try {
pcs.firePropertyChange(eventType, moduleName, null); pcs.firePropertyChange(eventType, jobId, null);
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, "Ingest manager listener threw exception", e); logger.log(Level.SEVERE, "Ingest manager listener threw exception", e);
MessageNotifyUtil.Notify.show(NbBundle.getMessage(IngestManager.class, "IngestManager.moduleErr"), MessageNotifyUtil.Notify.show(NbBundle.getMessage(IngestManager.class, "IngestManager.moduleErr"),
@ -163,11 +207,11 @@ public class IngestManager {
/** /**
* Fire event when file is done with a pipeline run * Fire event when file is done with a pipeline run
* *
* @param objId ID of file that is done * @param fileId ID of file that is done
*/ */
static synchronized void fireFileDone(long objId) { static void fireFileIngestDone(long fileId) {
try { try {
pcs.firePropertyChange(IngestEvent.FILE_DONE.toString(), objId, null); pcs.firePropertyChange(IngestEvent.FILE_DONE.toString(), fileId, null);
} catch (Exception e) { } catch (Exception e) {
logger.log(Level.SEVERE, "Ingest manager listener threw exception", e); logger.log(Level.SEVERE, "Ingest manager listener threw exception", e);
MessageNotifyUtil.Notify.show(NbBundle.getMessage(IngestManager.class, "IngestManager.moduleErr"), MessageNotifyUtil.Notify.show(NbBundle.getMessage(IngestManager.class, "IngestManager.moduleErr"),
@ -182,7 +226,7 @@ public class IngestManager {
* *
* @param moduleDataEvent * @param moduleDataEvent
*/ */
static synchronized void fireModuleDataEvent(ModuleDataEvent moduleDataEvent) { static void fireModuleDataEvent(ModuleDataEvent moduleDataEvent) {
try { try {
pcs.firePropertyChange(IngestEvent.DATA.toString(), moduleDataEvent, null); pcs.firePropertyChange(IngestEvent.DATA.toString(), moduleDataEvent, null);
} catch (Exception e) { } catch (Exception e) {
@ -199,7 +243,7 @@ public class IngestManager {
* *
* @param moduleContentEvent * @param moduleContentEvent
*/ */
static synchronized void fireModuleContentEvent(ModuleContentEvent moduleContentEvent) { static void fireModuleContentEvent(ModuleContentEvent moduleContentEvent) {
try { try {
pcs.firePropertyChange(IngestEvent.CONTENT_CHANGED.toString(), moduleContentEvent, null); pcs.firePropertyChange(IngestEvent.CONTENT_CHANGED.toString(), moduleContentEvent, null);
} catch (Exception e) { } catch (Exception e) {
@ -210,152 +254,6 @@ public class IngestManager {
} }
} }
/**
* Multiple data-sources version of scheduleDataSource() method. Enqueues
* multiple sources inputs (Content objects) and associated modules at once
*
* @param modules modules to scheduleDataSource on every data source
* @param inputs input data sources to enqueue and scheduleDataSource the
* ingest modules on
*/
void scheduleDataSourceTasks(final List<Content> dataSources, final List<IngestModuleTemplate> moduleTemplates, boolean processUnallocatedSpace) {
if (!isIngestRunning() && ingestMessageBox != null) {
ingestMessageBox.clearMessages();
}
taskSchedulingWorker = new TaskSchedulingWorker(dataSources, moduleTemplates, processUnallocatedSpace);
taskSchedulingWorker.execute();
if (ingestMessageBox != null) {
ingestMessageBox.restoreMessages();
}
}
/**
* IngestManager entry point, enqueues data to be processed and starts new
* ingest as needed, or just enqueues data to an existing pipeline.
*
* Spawns background thread which enumerates all sorted files and executes
* chosen modules per file in a pre-determined order. Notifies modules when
* work is complete or should be interrupted using complete() and stop()
* calls. Does not block and can be called multiple times to enqueue more
* work to already running background ingest process.
*
* @param modules modules to scheduleDataSource on the data source input
* @param input input data source Content objects to scheduleDataSource the
* ingest modules on
*/
void scheduleDataSourceTask(final Content dataSource, final List<IngestModuleTemplate> moduleTemplates, boolean processUnallocatedSpace) {
List<Content> dataSources = new ArrayList<>();
dataSources.add(dataSource);
scheduleDataSourceTasks(dataSources, moduleTemplates, processUnallocatedSpace);
}
/**
* Schedule a file for ingest and add it to ongoing file ingest process on
* the same data source. Scheduler updates the current progress.
*
* The file to be added is usually a product of a currently ran ingest. Now
* we want to process this new file with the same ingest context.
*
* @param file file to be scheduled
* @param pipelineContext ingest context used to ingest parent of the file
* to be scheduled
*/
void scheduleFile(long ingestJobId, AbstractFile file) {
IngestJob job = this.ingestJobs.get(ingestJobId);
if (job == null) {
logger.log(Level.SEVERE, "Unable to map ingest job id (id = {0}) to an ingest job, failed to schedule file (id = {1})", new Object[]{ingestJobId, file.getId()});
MessageNotifyUtil.Notify.show(NbBundle.getMessage(IngestManager.class, "IngestManager.moduleErr"),
"Unable to associate " + file.getName() + " with ingest job, file will not be processed by ingest nodules",
MessageNotifyUtil.MessageType.ERROR);
}
scheduler.getFileScheduler().scheduleFile(job, file);
}
/**
* Starts the File-level Ingest Module pipeline and the Data Source-level
* Ingest Modules for the queued up data sources and files.
*
* if AbstractFile module is still running, do nothing and allow it to
* consume queue otherwise start /restart AbstractFile worker
*
* data source ingest workers run per (module,content). Checks if one for
* the same (module,content) is already running otherwise start/restart the
* worker
*/
private synchronized void startAll() {
if (!ingestMonitor.isRunning()) {
ingestMonitor.start();
}
if (scheduler.getDataSourceScheduler().hasNext()) {
if (dataSourceTaskWorker == null || dataSourceTaskWorker.isDone()) {
dataSourceTaskWorker = new DataSourceTaskWorker(getNextThreadId());
dataSourceTaskWorker.execute();
}
}
if (scheduler.getFileScheduler().hasNext()) {
if (fileTaskWorker == null || fileTaskWorker.isDone()) {
fileTaskWorker = new FileTaskWorker(getNextThreadId());
fileTaskWorker.execute();
}
}
}
synchronized void reportThreadDone(long threadId) {
for (IngestJob job : ingestJobs.values()) {
job.releaseIngestPipelinesForThread(threadId);
if (job.areIngestPipelinesShutDown()) {
ingestJobs.remove(job.getId());
}
}
}
synchronized void stopAll() {
// First get the task scheduling worker to stop.
if (taskSchedulingWorker != null) {
taskSchedulingWorker.cancel(true);
while (!taskSchedulingWorker.isDone()) {
// Wait.
}
taskSchedulingWorker = null;
}
// Now mark all of the ingest jobs as cancelled. This way the ingest
// modules will know they are being shut down due to cancellation when
// the ingest worker threads release their pipelines.
for (IngestJob job : ingestJobs.values()) {
job.cancel();
}
// Cancel the worker threads.
if (dataSourceTaskWorker != null) {
dataSourceTaskWorker.cancel(true);
}
if (fileTaskWorker != null) {
fileTaskWorker.cancel(true);
}
// Jettision the remaining tasks. This will dispose of any tasks that
// the scheduling worker queued up before it was cancelled.
scheduler.getFileScheduler().empty();
scheduler.getDataSourceScheduler().empty();
}
/**
* Test if any ingest modules are running
*
* @return true if any module is running, false otherwise
*/
public synchronized boolean isIngestRunning() {
return ((taskSchedulingWorker != null && !taskSchedulingWorker.isDone())
|| (fileTaskWorker != null && !fileTaskWorker.isDone())
|| (fileTaskWorker != null && !fileTaskWorker.isDone()));
}
/** /**
* Module publishes message using InegestManager handle Does not block. The * Module publishes message using InegestManager handle Does not block. The
* message gets enqueued in the GUI thread and displayed in a widget * message gets enqueued in the GUI thread and displayed in a widget
@ -384,82 +282,219 @@ public class IngestManager {
} }
} }
private class TaskSchedulingWorker extends SwingWorker<Object, Void> { private synchronized void startIngestTasks() {
if (!ingestMonitor.isRunning()) {
ingestMonitor.start();
}
long taskId = ingestTaskId.incrementAndGet();
Future<?> task = dataSourceIngestTasksExecutor.submit(new RunDataSourceIngestModulesTask(taskId));
ingestTasks.put(taskId, task);
int numberOfFileTasksRequested = getNumberOfFileIngestThreads();
for (int i = 0; i < numberOfFileTasksRequested; ++i) {
taskId = ingestTaskId.incrementAndGet();
task = fileIngestTasksExecutor.submit(new RunFileSourceIngestModulesTask(taskId));
ingestTasks.put(taskId, task);
}
}
private synchronized void stopIngestTasks() {
// First mark all of the ingest jobs as cancelled. This way the
// ingest modules will know they are being shut down due to
// cancellation when the cancelled run ingest module tasks release
// their pipelines.
for (IngestJob job : ingestJobs.values()) {
job.cancel();
}
// Cancel the run ingest module tasks, setting the state of the threads
// running them to interrupted.
for (Future<?> task : ingestTasks.values()) {
task.cancel(true);
}
// Jettision the remaining data source and file ingest tasks.
scheduler.getFileScheduler().empty();
scheduler.getDataSourceScheduler().empty();
}
synchronized void reportStartIngestJobsTaskDone(long taskId) {
ingestTasks.remove(taskId);
}
synchronized void reportRunIngestModulesTaskDone(long taskId) {
ingestTasks.remove(taskId);
List<Long> completedJobs = new ArrayList<>();
for (IngestJob job : ingestJobs.values()) {
job.releaseIngestPipelinesForThread(taskId);
if (job.areIngestPipelinesShutDown() == true) {
completedJobs.add(job.getId());
}
}
for (Long jobId : completedJobs) {
IngestJob job = ingestJobs.remove(jobId);
fireIngestJobEvent(job.isCancelled() ? IngestEvent.INGEST_JOB_CANCELLED.toString() : IngestEvent.INGEST_JOB_COMPLETED.toString(), jobId);
}
}
private class StartIngestJobsTask implements Runnable {
private final long id;
private final List<Content> dataSources; private final List<Content> dataSources;
private final List<IngestModuleTemplate> moduleTemplates; private final List<IngestModuleTemplate> moduleTemplates;
private final boolean processUnallocatedSpace; private final boolean processUnallocatedSpace;
private ProgressHandle progress; private ProgressHandle progress;
TaskSchedulingWorker(List<Content> dataSources, List<IngestModuleTemplate> moduleTemplates, boolean processUnallocatedSpace) { StartIngestJobsTask(long taskId, List<Content> dataSources, List<IngestModuleTemplate> moduleTemplates, boolean processUnallocatedSpace) {
this.id = taskId;
this.dataSources = dataSources; this.dataSources = dataSources;
this.moduleTemplates = moduleTemplates; this.moduleTemplates = moduleTemplates;
this.processUnallocatedSpace = processUnallocatedSpace; this.processUnallocatedSpace = processUnallocatedSpace;
} }
@Override @Override
protected Object doInBackground() throws Exception { public void run() {
// Set up a progress bar that can be used to cancel all of the try {
// ingest jobs currently being performed. final String displayName = "Queueing ingest tasks";
final String displayName = "Queueing ingest tasks"; progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override
@Override public boolean cancel() {
public boolean cancel() { if (progress != null) {
logger.log(Level.INFO, "Queueing ingest cancelled by user."); progress.setDisplayName(displayName + " (Cancelling...)");
if (progress != null) {
progress.setDisplayName(displayName + " (Cancelling...)");
}
IngestManager.getDefault().stopAll();
return true;
}
});
progress.start(2 * dataSources.size());
int processed = 0;
for (Content dataSource : dataSources) {
if (isCancelled()) {
logger.log(Level.INFO, "Task scheduling thread cancelled");
return null;
}
final String inputName = dataSource.getName();
IngestJob ingestJob = new IngestJob(IngestManager.this.getNextDataSourceTaskId(), dataSource, moduleTemplates, processUnallocatedSpace);
List<IngestModuleError> errors = ingestJob.startUpIngestPipelines();
if (!errors.isEmpty()) {
StringBuilder failedModules = new StringBuilder();
for (int i = 0; i < errors.size(); ++i) {
IngestModuleError error = errors.get(i);
String moduleName = error.getModuleDisplayName();
logger.log(Level.SEVERE, "The " + moduleName + " module failed to start up", error.getModuleError());
failedModules.append(moduleName);
if ((errors.size() > 1) && (i != (errors.size() - 1))) {
failedModules.append(",");
} }
IngestManager.getInstance().cancelIngestJobs();
return true;
}
});
progress.start(2 * dataSources.size());
int workUnitsCompleted = 0;
for (Content dataSource : dataSources) {
if (Thread.currentThread().isInterrupted()) {
break;
}
IngestJob ingestJob = new IngestJob(IngestManager.this.ingestJobId.incrementAndGet(), dataSource, moduleTemplates, processUnallocatedSpace);
List<IngestModuleError> errors = ingestJob.startUpIngestPipelines();
if (!errors.isEmpty()) {
StringBuilder failedModules = new StringBuilder();
for (int i = 0; i < errors.size(); ++i) {
IngestModuleError error = errors.get(i);
String moduleName = error.getModuleDisplayName();
logger.log(Level.SEVERE, "The " + moduleName + " module failed to start up", error.getModuleError());
failedModules.append(moduleName);
if ((errors.size() > 1) && (i != (errors.size() - 1))) {
failedModules.append(",");
}
}
MessageNotifyUtil.Message.error( // RJCTODO: Fix this to show all errors, probably should specify data source name
"Failed to start the following ingest modules: " + failedModules.toString() + " .\n\n"
+ "No ingest modules will be run. Please disable the module "
+ "or fix the error and restart ingest by right clicking on "
+ "the data source and selecting Run Ingest Modules.\n\n"
+ "Error: " + errors.get(0).getModuleError().getMessage());
ingestJob.cancel();
break;
}
// Save the ingest job for later cleanup of pipelines.
synchronized (IngestManager.this) {
ingestJobs.put(ingestJob.getId(), ingestJob);
}
// Queue the data source ingest tasks for the ingest job.
final String inputName = dataSource.getName();
progress.progress("Data source ingest tasks for " + inputName, workUnitsCompleted); // RJCTODO: Improve
scheduler.getDataSourceScheduler().schedule(ingestJob);
progress.progress("Data source ingest tasks for " + inputName, ++workUnitsCompleted);
// Queue the file ingest tasks for the ingest job.
progress.progress("Data source ingest tasks for " + inputName, workUnitsCompleted);
scheduler.getFileScheduler().scheduleIngestOfFiles(ingestJob);
progress.progress("Data source ingest tasks for " + inputName, ++workUnitsCompleted);
if (!Thread.currentThread().isInterrupted()) {
startIngestTasks();
fireIngestJobEvent(IngestEvent.INGEST_JOB_STARTED.toString(), ingestJob.getId());
} }
MessageNotifyUtil.Message.error(
"Failed to start the following ingest modules: " + failedModules.toString() + " .\n\n"
+ "No ingest modules will be run. Please disable the module "
+ "or fix the error and restart ingest by right clicking on "
+ "the data source and selecting Run Ingest Modules.\n\n"
+ "Error: " + errors.get(0).getModuleError().getMessage());
return null;
} }
} catch (Exception ex) {
// Save the ingest job for later cleanup of pipelines. String message = String.format("StartIngestJobsTask (id=%d) caught exception", id);
ingestJobs.put(ingestJob.getId(), ingestJob); logger.log(Level.SEVERE, message, ex);
MessageNotifyUtil.Message.error("An error occurred while starting ingest. Results may only be partial");
// Queue the data source ingest tasks for the ingest job. } finally {
progress.progress("DataSource Ingest" + " " + inputName, processed); progress.finish();
scheduler.getDataSourceScheduler().schedule(ingestJob); reportStartIngestJobsTaskDone(id);
progress.progress("DataSource Ingest" + " " + inputName, ++processed);
// Queue the file ingest tasks for the ingest job.
progress.progress("File Ingest" + " " + inputName, processed);
scheduler.getFileScheduler().scheduleIngestOfFiles(ingestJob);
progress.progress("File Ingest" + " " + inputName, ++processed);
} }
}
}
private class RunDataSourceIngestModulesTask implements Runnable {
private final long id;
RunDataSourceIngestModulesTask(long taskId) {
id = taskId;
}
@Override
public void run() {
try {
IngestScheduler.DataSourceScheduler scheduler = IngestScheduler.getInstance().getDataSourceScheduler();
while (scheduler.hasNext()) {
if (Thread.currentThread().isInterrupted()) {
break;
}
IngestJob job = scheduler.next();
job.getDataSourceIngestPipelineForThread(id).process();
}
} catch (Exception ex) {
String message = String.format("RunDataSourceIngestModulesTask (id=%d) caught exception", id);
logger.log(Level.SEVERE, message, ex);
} finally {
reportRunIngestModulesTaskDone(id);
}
}
}
private class RunFileSourceIngestModulesTask implements Runnable {
private final long id;
RunFileSourceIngestModulesTask(long taskId) {
id = taskId;
}
@Override
public void run() {
try {
IngestScheduler.FileScheduler fileScheduler = IngestScheduler.getInstance().getFileScheduler();
while (fileScheduler.hasNext()) {
if (Thread.currentThread().isInterrupted()) {
break;
}
IngestScheduler.FileScheduler.FileTask task = fileScheduler.next();
IngestJob job = task.getJob();
job.updateFileTasksProgressBar(task.getFile().getName());
job.getFileIngestPipelineForThread(id).process(task.getFile());
}
} catch (Exception ex) {
String message = String.format("RunFileSourceIngestModulesTask (id=%d) caught exception", id);
logger.log(Level.SEVERE, message, ex);
} finally {
reportRunIngestModulesTaskDone(id);
}
}
}
class IngestCancellationWorker extends SwingWorker<Void, Void> {
@Override
protected Void doInBackground() throws Exception {
stopIngestTasks();
return null; return null;
} }
@ -468,172 +503,8 @@ public class IngestManager {
try { try {
super.get(); super.get();
} catch (CancellationException | InterruptedException ex) { } catch (CancellationException | InterruptedException ex) {
// IngestManager.stopAll() will dispose of all tasks.
} catch (Exception ex) { } catch (Exception ex) {
logger.log(Level.SEVERE, "Error while scheduling ingest jobs", ex); logger.log(Level.SEVERE, "Error while cancelling ingest jobs", ex);
MessageNotifyUtil.Message.error("An error occurred while starting ingest. Results may only be partial");
} finally {
if (!isCancelled()) {
startAll();
}
progress.finish();
}
}
}
/**
* Performs data source ingest tasks for one or more ingest jobs on a worker
* thread.
*/
class DataSourceTaskWorker extends SwingWorker<Object, Void> {
private final long id;
private ProgressHandle progress;
DataSourceTaskWorker(long threadId) {
this.id = threadId;
}
@Override
protected Void doInBackground() throws Exception {
logger.log(Level.INFO, "Data source ingest thread (id={0}) started", this.id);
// Set up a progress bar that can be used to cancel all of the
// ingest jobs currently being performed.
progress = ProgressHandleFactory.createHandle("Data source ingest", new Cancellable() {
@Override
public boolean cancel() {
logger.log(Level.INFO, "Data source ingest thread (id={0}) cancelled", DataSourceTaskWorker.this.id);
if (progress != null) {
progress.setDisplayName(NbBundle.getMessage(this.getClass(),
"IngestManager.DataSourceTaskWorker.process.cancelling",
"Data source ingest"));
}
IngestManager.getDefault().stopAll();
return true;
}
});
progress.start();
progress.switchToIndeterminate();
IngestScheduler.DataSourceScheduler scheduler = IngestScheduler.getInstance().getDataSourceScheduler();
while (scheduler.hasNext()) {
if (isCancelled()) {
logger.log(Level.INFO, "Data source ingest thread (id={0}) cancelled", this.id);
return null;
}
IngestJob ingestJob = scheduler.next();
IngestJob.DataSourceIngestPipeline pipeline = ingestJob.getDataSourceIngestPipelineForThread(this.id);
pipeline.process(this, this.progress);
}
logger.log(Level.INFO, "Data source ingest thread (id={0}) completed", this.id);
IngestManager.getDefault().reportThreadDone(this.id);
return null;
}
@Override
protected void done() {
try {
super.get();
} catch (CancellationException | InterruptedException e) {
logger.log(Level.INFO, "Data source ingest thread (id={0}) cancelled", this.id);
IngestManager.getDefault().reportThreadDone(this.id);
} catch (Exception ex) {
String message = String.format("Data source ingest thread (id=%d) experienced a fatal error", this.id);
logger.log(Level.SEVERE, message, ex);
IngestManager.getDefault().reportThreadDone(this.id);
} finally {
progress.finish();
}
}
}
/**
* Performs file ingest tasks for one or more ingest jobs on a worker
* thread.
*/
class FileTaskWorker extends SwingWorker<Object, Void> {
private final long id;
private ProgressHandle progress;
FileTaskWorker(long threadId) {
this.id = threadId;
}
@Override
protected Object doInBackground() throws Exception {
logger.log(Level.INFO, "File ingest thread (id={0}) started", this.id);
// Set up a progress bar that can be used to cancel all of the
// ingest jobs currently being performed.
final String displayName = NbBundle
.getMessage(this.getClass(), "IngestManager.FileTaskWorker.displayName");
progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() {
@Override
public boolean cancel() {
logger.log(Level.INFO, "File ingest thread (id={0}) cancelled", FileTaskWorker.this.id);
if (progress != null) {
progress.setDisplayName(
NbBundle.getMessage(this.getClass(), "IngestManager.FileTaskWorker.process.cancelling",
displayName));
}
IngestManager.getDefault().stopAll();
return true;
}
});
progress.start();
progress.switchToIndeterminate();
IngestScheduler.FileScheduler fileScheduler = IngestScheduler.getInstance().getFileScheduler();
int totalEnqueuedFiles = fileScheduler.getFilesEnqueuedEst();
progress.switchToDeterminate(totalEnqueuedFiles);
int processedFiles = 0;
while (fileScheduler.hasNext()) {
if (isCancelled()) {
IngestManager.getDefault().reportThreadDone(this.id);
logger.log(Level.INFO, "File ingest thread (id={0}) cancelled", this.id);
return null;
}
IngestScheduler.FileScheduler.FileTask task = fileScheduler.next();
AbstractFile file = task.getFile();
progress.progress(file.getName(), processedFiles);
IngestJob.FileIngestPipeline pipeline = task.getJob().getFileIngestPipelineForThread(this.id);
pipeline.process(file);
// Update the progress bar.
int newTotalEnqueuedFiles = fileScheduler.getFilesEnqueuedEst();
if (newTotalEnqueuedFiles > totalEnqueuedFiles) {
totalEnqueuedFiles = newTotalEnqueuedFiles + 1;
progress.switchToIndeterminate();
progress.switchToDeterminate(totalEnqueuedFiles);
}
if (processedFiles < totalEnqueuedFiles) {
++processedFiles;
}
}
logger.log(Level.INFO, "File ingest thread (id={0}) completed", this.id);
IngestManager.getDefault().reportThreadDone(this.id);
return null;
}
@Override
protected void done() {
try {
super.get();
} catch (CancellationException | InterruptedException e) {
logger.log(Level.INFO, "File ingest thread (id={0}) cancelled", this.id);
IngestManager.getDefault().reportThreadDone(this.id);
} catch (Exception ex) {
String message = String.format("File ingest thread {0} experienced a fatal error", this.id);
logger.log(Level.SEVERE, message, ex);
IngestManager.getDefault().reportThreadDone(this.id);
} finally {
progress.finish();
} }
} }
} }

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.ingest;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -48,6 +49,7 @@ public class IngestMessage {
private Date datePosted; private Date datePosted;
private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private static int managerMessageId = 0; private static int managerMessageId = 0;
private static AtomicLong nextMessageID = new AtomicLong(0);
/** /**
* Private constructor used by factory methods * Private constructor used by factory methods
@ -175,11 +177,12 @@ public class IngestMessage {
* @param detailsHtml html formatted detailed message (without leading and closing &lt;html&gt; tags), for instance, a human-readable representation of the data. Or null. * @param detailsHtml html formatted detailed message (without leading and closing &lt;html&gt; tags), for instance, a human-readable representation of the data. Or null.
* @return * @return
*/ */
public static IngestMessage createMessage(long ID, MessageType messageType, String source, String subject, String detailsHtml) { public static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml) {
if (messageType == null || source == null || subject == null) { if (messageType == null || source == null || subject == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.typeSrcSubjNotNull.msg")); NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.typeSrcSubjNotNull.msg"));
} }
long ID = nextMessageID.getAndIncrement();
return new IngestMessage(ID, messageType, source, subject, detailsHtml, null); return new IngestMessage(ID, messageType, source, subject, detailsHtml, null);
} }
@ -191,8 +194,8 @@ public class IngestMessage {
* @param subject message subject to be displayed * @param subject message subject to be displayed
* @return * @return
*/ */
public static IngestMessage createMessage(long ID, MessageType messageType, String source, String subject) { public static IngestMessage createMessage(MessageType messageType, String source, String subject) {
return createMessage(ID, messageType, source, subject, null); return createMessage(messageType, source, subject, null);
} }
@ -204,11 +207,12 @@ public class IngestMessage {
* @param detailsHtml html formatted detailed message (without leading and closing &lt;html&gt; tags), for instance, a human-readable representation of the data. Or null * @param detailsHtml html formatted detailed message (without leading and closing &lt;html&gt; tags), for instance, a human-readable representation of the data. Or null
* @return * @return
*/ */
public static IngestMessage createErrorMessage(long ID, String source, String subject, String detailsHtml) { public static IngestMessage createErrorMessage(String source, String subject, String detailsHtml) {
if (source == null || subject == null) { if (source == null || subject == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.srcSubjNotNull.msg")); NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.srcSubjNotNull.msg"));
} }
long ID = nextMessageID.getAndIncrement();
return new IngestMessage(ID, MessageType.ERROR, source, subject, detailsHtml, null); return new IngestMessage(ID, MessageType.ERROR, source, subject, detailsHtml, null);
} }
@ -220,11 +224,12 @@ public class IngestMessage {
* @param detailsHtml html formatted detailed message (without leading and closing &lt;html&gt; tags), for instance, a human-readable representation of the data. Or null * @param detailsHtml html formatted detailed message (without leading and closing &lt;html&gt; tags), for instance, a human-readable representation of the data. Or null
* @return * @return
*/ */
public static IngestMessage createWarningMessage(long ID, String source, String subject, String detailsHtml) { public static IngestMessage createWarningMessage(String source, String subject, String detailsHtml) {
if (source == null || subject == null) { if (source == null || subject == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.srcSubjNotNull.msg")); NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.srcSubjNotNull.msg"));
} }
long ID = nextMessageID.getAndIncrement();
return new IngestMessage(ID, MessageType.WARNING, source, subject, detailsHtml, null); return new IngestMessage(ID, MessageType.WARNING, source, subject, detailsHtml, null);
} }
@ -238,12 +243,13 @@ public class IngestMessage {
* @param data blackboard artifact associated with the message, the same as fired in ModuleDataEvent by the module * @param data blackboard artifact associated with the message, the same as fired in ModuleDataEvent by the module
* @return * @return
*/ */
public static IngestMessage createDataMessage(long ID, String source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data) { public static IngestMessage createDataMessage(String source, String subject, String detailsHtml, String uniqueKey, BlackboardArtifact data) {
if (source == null || subject == null || detailsHtml == null || data == null) { if (source == null || subject == null || detailsHtml == null || data == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.srcSubjDetailsDataNotNull.msg")); NbBundle.getMessage(IngestMessage.class, "IngestMessage.exception.srcSubjDetailsDataNotNull.msg"));
} }
long ID = nextMessageID.getAndIncrement();
IngestMessage im = new IngestMessage(ID, MessageType.DATA, source, subject, detailsHtml, uniqueKey); IngestMessage im = new IngestMessage(ID, MessageType.DATA, source, subject, detailsHtml, uniqueKey);
im.data = data; im.data = data;
return im; return im;

View File

@ -395,18 +395,18 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
} }
@Override @Override
synchronized public int getRowCount() { public synchronized int getRowCount() {
return getNumberGroups(); return getNumberGroups();
} }
public void markAllSeen() { public synchronized void markAllSeen() {
for (TableEntry entry : messageData) { for (TableEntry entry : messageData) {
entry.hasBeenSeen(true); entry.hasBeenSeen(true);
} }
fireTableChanged(new TableModelEvent(this)); fireTableChanged(new TableModelEvent(this));
} }
public int getNumberNewMessages() { public synchronized int getNumberNewMessages() {
int newMessages = 0; int newMessages = 0;
for (TableEntry entry : messageData) { for (TableEntry entry : messageData) {
if (!entry.hasBeenSeen()) { if (!entry.hasBeenSeen()) {
@ -416,11 +416,11 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
return newMessages; return newMessages;
} }
synchronized int getNumberGroups() { public synchronized int getNumberGroups() {
return messageData.size(); return messageData.size();
} }
synchronized int getNumberMessages() { public synchronized int getNumberMessages() {
int total = 0; int total = 0;
for (TableEntry e : messageData) { for (TableEntry e : messageData) {
total += e.messageGroup.getCount(); total += e.messageGroup.getCount();
@ -428,7 +428,7 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
return total; return total;
} }
synchronized int getNumberUnreadMessages() { public synchronized int getNumberUnreadMessages() {
int total = 0; int total = 0;
for (TableEntry e : messageData) { for (TableEntry e : messageData) {
if (!e.hasBeenVisited) { if (!e.hasBeenVisited) {
@ -438,7 +438,7 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
return total; return total;
} }
synchronized int getNumberUnreadGroups() { public synchronized int getNumberUnreadGroups() {
int total = 0; int total = 0;
for (TableEntry e : messageData) { for (TableEntry e : messageData) {
if (!e.hasBeenVisited) { if (!e.hasBeenVisited) {
@ -513,7 +513,7 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
return ret; return ret;
} }
synchronized public void addMessage(IngestMessage m) { public synchronized void addMessage(IngestMessage m) {
//check how many messages per module with the same uniqness //check how many messages per module with the same uniqness
//and add to existing group or create a new group //and add to existing group or create a new group
String moduleName = m.getSource(); String moduleName = m.getSource();
@ -628,15 +628,27 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
} }
public synchronized boolean isVisited(int rowNumber) { public synchronized boolean isVisited(int rowNumber) {
return messageData.get(rowNumber).hasBeenVisited(); if (rowNumber < messageData.size()) {
return messageData.get(rowNumber).hasBeenVisited();
} else {
return false;
}
} }
public synchronized MessageType getMessageType(int rowNumber) { public synchronized MessageType getMessageType(int rowNumber) {
return messageData.get(rowNumber).messageGroup.getMessageType(); if (rowNumber < messageData.size()) {
return messageData.get(rowNumber).messageGroup.getMessageType();
} else {
return null;
}
} }
public synchronized IngestMessageGroup getMessageGroup(int rowNumber) { public synchronized IngestMessageGroup getMessageGroup(int rowNumber) {
return messageData.get(rowNumber).messageGroup; if (rowNumber < messageData.size()) {
return messageData.get(rowNumber).messageGroup;
} else {
return null;
}
} }
public synchronized void reSort(boolean chronoLogical) { public synchronized void reSort(boolean chronoLogical) {
@ -701,26 +713,26 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
messages.add(message); messages.add(message);
} }
List<IngestMessage> getMessages() { private List<IngestMessage> getMessages() {
return messages; return messages;
} }
void add(IngestMessage message) { synchronized void add(IngestMessage message) {
messages.add(message); messages.add(message);
} }
//add all messages from another group //add all messages from another group
void addAll(IngestMessageGroup group) { synchronized void addAll(IngestMessageGroup group) {
for (IngestMessage m : group.getMessages()) { for (IngestMessage m : group.getMessages()) {
messages.add(m); messages.add(m);
} }
} }
int getCount() { synchronized int getCount() {
return messages.size(); return messages.size();
} }
String getDetails() { synchronized String getDetails() {
StringBuilder b = new StringBuilder(""); StringBuilder b = new StringBuilder("");
for (IngestMessage m : messages) { for (IngestMessage m : messages) {
String details = m.getDetails(); String details = m.getDetails();
@ -739,7 +751,7 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
* return color corresp to priority * return color corresp to priority
* @return * @return
*/ */
Color getColor() { synchronized Color getColor() {
int count = messages.size(); int count = messages.size();
if (count == 1) { if (count == 1) {
return VERY_HIGH_PRI_COLOR; return VERY_HIGH_PRI_COLOR;
@ -757,7 +769,7 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
* used for chrono sort * used for chrono sort
* @return * @return
*/ */
Date getDatePosted() { synchronized Date getDatePosted() {
return messages.get(messages.size() - 1).getDatePosted(); return messages.get(messages.size() - 1).getDatePosted();
} }
@ -765,35 +777,35 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
* get subject of the first message * get subject of the first message
* @return * @return
*/ */
String getSubject() { synchronized String getSubject() {
return messages.get(0).getSubject(); return messages.get(0).getSubject();
} }
/* /*
* return unique key, should be the same for all msgs * return unique key, should be the same for all msgs
*/ */
String getUniqueKey() { synchronized String getUniqueKey() {
return messages.get(0).getUniqueKey(); return messages.get(0).getUniqueKey();
} }
/* /*
* return source module, should be the same for all msgs * return source module, should be the same for all msgs
*/ */
String getSource() { synchronized String getSource() {
return messages.get(0).getSource(); return messages.get(0).getSource();
} }
/* /*
* return data of the first message * return data of the first message
*/ */
BlackboardArtifact getData() { synchronized BlackboardArtifact getData() {
return messages.get(0).getData(); return messages.get(0).getData();
} }
/* /*
* return message type, should be the same for all msgs * return message type, should be the same for all msgs
*/ */
IngestMessage.MessageType getMessageType() { synchronized IngestMessage.MessageType getMessageType() {
return messages.get(0).getMessageType(); return messages.get(0).getMessageType();
} }
} }
@ -858,16 +870,17 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
cell.setFont(new Font("", Font.PLAIN, 16)); cell.setFont(new Font("", Font.PLAIN, 16));
final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row); final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row);
MessageType mt = messageGroup.getMessageType(); if (messageGroup != null) {
if (mt == MessageType.ERROR) { MessageType mt = messageGroup.getMessageType();
cell.setBackground(ERROR_COLOR); if (mt == MessageType.ERROR) {
} else if (mt == MessageType.WARNING) { cell.setBackground(ERROR_COLOR);
cell.setBackground(Color.orange); } else if (mt == MessageType.WARNING) {
} else { cell.setBackground(Color.orange);
//cell.setBackground(table.getBackground()); } else {
cell.setBackground(messageGroup.getColor()); //cell.setBackground(table.getBackground());
cell.setBackground(messageGroup.getColor());
}
} }
return cell; return cell;
} }
} }
@ -898,16 +911,17 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
} }
final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row); final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row);
MessageType mt = messageGroup.getMessageType(); if (messageGroup != null) {
if (mt == MessageType.ERROR) { MessageType mt = messageGroup.getMessageType();
cell.setBackground(ERROR_COLOR); if (mt == MessageType.ERROR) {
} else if (mt == MessageType.WARNING) { cell.setBackground(ERROR_COLOR);
cell.setBackground(Color.orange); } else if (mt == MessageType.WARNING) {
} else { cell.setBackground(Color.orange);
//cell.setBackground(table.getBackground()); } else {
cell.setBackground(messageGroup.getColor()); //cell.setBackground(table.getBackground());
cell.setBackground(messageGroup.getColor());
}
} }
return cell; return cell;
} }
} }
@ -933,14 +947,16 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
Component cell = super.getTableCellRendererComponent(table, aValue, isSelected, hasFocus, row, column); Component cell = super.getTableCellRendererComponent(table, aValue, isSelected, hasFocus, row, column);
final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row); final IngestMessageGroup messageGroup = tableModel.getMessageGroup(row);
MessageType mt = messageGroup.getMessageType(); if (messageGroup != null) {
if (mt == MessageType.ERROR) { MessageType mt = messageGroup.getMessageType();
cell.setBackground(ERROR_COLOR); if (mt == MessageType.ERROR) {
} else if (mt == MessageType.WARNING) { cell.setBackground(ERROR_COLOR);
cell.setBackground(Color.orange); } else if (mt == MessageType.WARNING) {
} else { cell.setBackground(Color.orange);
//cell.setBackground(table.getBackground()); } else {
cell.setBackground(messageGroup.getColor()); //cell.setBackground(table.getBackground());
cell.setBackground(messageGroup.getColor());
}
} }
return cell; return cell;
@ -974,9 +990,11 @@ class IngestMessagePanel extends JPanel implements TableModelListener {
messageTable.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); messageTable.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
//check if has details //check if has details
IngestMessageGroup m = getMessageGroup(selected); IngestMessageGroup m = getMessageGroup(selected);
String details = m.getDetails(); if (m != null) {
if (details != null && !details.equals("")) { String details = m.getDetails();
mainPanel.showDetails(selected); if (details != null && !details.equals("")) {
mainPanel.showDetails(selected);
}
} }
messageTable.setCursor(null); messageTable.setCursor(null);
} }

View File

@ -126,7 +126,7 @@ import org.sleuthkit.datamodel.Content;
super.componentOpened(); super.componentOpened();
//create manager instance //create manager instance
if (manager == null) { if (manager == null) {
manager = IngestManager.getDefault(); manager = IngestManager.getInstance();
} }
} }
@ -221,10 +221,10 @@ import org.sleuthkit.datamodel.Content;
} }
//stop workers if running //stop workers if running
if (manager == null) { if (manager == null) {
manager = IngestManager.getDefault(); manager = IngestManager.getInstance();
} }
try { try {
manager.stopAll(); manager.cancelIngestJobs();
} finally { } finally {
//clear inbox //clear inbox
clearMessages(); clearMessages();

View File

@ -20,28 +20,80 @@ package org.sleuthkit.autopsy.ingest;
/** /**
* The interface that must be implemented by all ingest modules. * The interface that must be implemented by all ingest modules.
*
* Autopsy will generally use several instances of an ingest module for each
* ingest job it performs (one for each thread that it is using).
*
* Autopsy will call startUp() before any data is processed, will pass any
* data to be analyzed into the process() method (FileIngestModule.process() or DataSourceIngestModule.process()),
* and call shutDown() after
* either all data is analyzed or the has has cancelled the job.
*
* Autopsy may use multiple threads to complete an ingest job, but it is
* guaranteed that a module instance will always be called from a single thread.
* Therefore, you can easily have thread-safe code by not using any static
* member variables.
*
* If the module instances must share resources, the modules are
* responsible for synchronizing access to the shared resources and doing
* reference counting as required to release those resources correctly. Also,
* more than one ingest job may be in progress at any given time. This must also
* be taken into consideration when sharing resources between module instances.
*
* TIP: An ingest module that does not require initialization or clean up may
* extend the abstract IngestModuleAdapter class to get a default "do nothing"
* implementation of this interface.
*/ */
public interface IngestModule { public interface IngestModule {
/**
* A return code for derived class process() methods.
*/
public enum ProcessResult { public enum ProcessResult {
OK, OK,
ERROR ERROR
}; };
/**
* A custom exception for the use of ingest modules.
*/
public class IngestModuleException extends Exception { public class IngestModuleException extends Exception {
public IngestModuleException() {
}
public IngestModuleException(String message) { public IngestModuleException(String message) {
super(message); super(message);
} }
} }
// RJCTODO: Write header comment, make sure to mention "one module instance per thread"
/** /**
* Invoked by the ingest frame * Invoked by Autopsy to allow an ingest module instance to set up any
* @param context * internal data structures and acquire any private resources it will need
* during an ingest job.
*
* If the module depends on loading any resources, it should do so in this
* method so that it can throw an exception in the case of an error and
* alert the user. Exceptions that are thrown from process() and shutDown()
* are logged, but do not stop processing of the data source.
*
* On error, throw a IngestModuleException.
*
* @param context Provides data and services specific to the ingest job and
* the ingest pipeline of which the module is a part.
* @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException * @throws org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException
*/ */
void startUp(IngestJobContext context) throws IngestModuleException; void startUp(IngestJobContext context) throws IngestModuleException;
// RJCTODO: Write header comment, make sure to mention "one module instance per thread" /**
* Invoked by Autopsy when an ingest job is completed (either because the
* data has been analyzed or because the job was cancelled), before the ingest
* module instance is discarded. The module should respond by doing things
* like releasing private resources, submitting final results, and posting a
* final ingest message.
* @param ingestJobWasCancelled True if this is being called because the user
* cancelled the job.
*/
void shutDown(boolean ingestJobWasCancelled); void shutDown(boolean ingestJobWasCancelled);
} }

View File

@ -23,7 +23,6 @@ package org.sleuthkit.autopsy.ingest;
* interface. * interface.
*/ */
public abstract class IngestModuleAdapter implements IngestModule { public abstract class IngestModuleAdapter implements IngestModule {
@Override @Override
public void startUp(IngestJobContext context) throws IngestModuleException { public void startUp(IngestJobContext context) throws IngestModuleException {
} }

View File

@ -19,34 +19,50 @@
package org.sleuthkit.autopsy.ingest; package org.sleuthkit.autopsy.ingest;
/** /**
* An interface that must be implemented by all providers of ingest modules. An * An interface that must be implemented by all providers of Autopsy ingest
* ingest module factory will be used to create instances of a type of data * modules. An ingest module factory is used to create instances of a type of
* source ingest module, a type of file ingest module, or both. * data source ingest module, a type of file ingest module, or both.
* <P>
* IMPORTANT: The factory should be stateless to support context-sensitive use
* of the factory. The ingest framework is responsible for managing context
* switching and the persistence of resource configurations and per ingest job
* options.
* <p> * <p>
* IMPORTANT: The ingest framework will create one or more instances of each * Autopsy will generally use the factory to create several instances of each
* module type for each ingest job it performs. The ingest framework may use * type of module for each ingest job it performs. Completing an ingest job
* multiple threads to complete an ingest job, but it is guaranteed that there * entails processing a single data source (e.g., a disk image) and all of the
* will be no more than one module instance per thread. However, if these * files from the data source, including files extracted from archives and any
* instances must share resources, the modules are responsible for synchronizing * unallocated space (made to look like a series of files). The data source is
* access to the shared resources and doing reference counting as required to * passed through one or more pipelines of data source ingest modules. The files
* release those resources correctly. * are passed through one or more pipelines of file ingest modules.
* <p> * <p>
* IMPORTANT: To be discovered at runtime by the ingest framework, * Autopsy may use multiple threads to complete an ingest job, but it is
* IngestModuleFactory implementations must be marked with the following * guaranteed that there will be no more than one module instance per thread.
* NetBeans Service provider annotation: * However, if the module instances must share resources, the modules are
* responsible for synchronizing access to the shared resources and doing
* reference counting as required to release those resources correctly. Also,
* more than one ingest job may be in progress at any given time. This must also
* be taken into consideration when sharing resources between module instances.
* <p>
* An ingest module factory may provide global and per ingest job settings user
* interface panels. The global settings should apply to all module instances.
* The per ingest job settings should apply to all module instances working on a
* particular ingest job. Autopsy supports context-sensitive and persistent per
* ingest job settings, so per ingest job settings must be serializable.
* <p>
* To be discovered at runtime by the ingest framework, IngestModuleFactory
* implementations must be marked with the following NetBeans Service provider
* annotation:
* *
* @ServiceProvider(service=IngestModuleFactory.class) * @ServiceProvider(service=IngestModuleFactory.class)
* <p>
* IMPORTANT TIP: If an implementation of IngestModuleFactory does not need to
* provide implementations of all of the IngestModuleFactory methods, it can
* extend the abstract class IngestModuleFactoryAdapter to get default
* implementations of most of the IngestModuleFactory methods.
*/ */
public interface IngestModuleFactory { public interface IngestModuleFactory {
/** /**
* Gets the display name that identifies the family of ingest modules the * Gets the display name that identifies the family of ingest modules the
* factory creates. * factory creates. Autopsy uses this string to identify the module in user
* interface components and log messages. The module name must be unique. so
* a brief but distinctive name is recommended.
* *
* @return The module family display name. * @return The module family display name.
*/ */
@ -54,7 +70,8 @@ public interface IngestModuleFactory {
/** /**
* Gets a brief, user-friendly description of the family of ingest modules * Gets a brief, user-friendly description of the family of ingest modules
* the factory creates. * the factory creates. Autopsy uses this string to describe the module in
* user interface components.
* *
* @return The module family description. * @return The module family description.
*/ */
@ -69,147 +86,154 @@ public interface IngestModuleFactory {
String getModuleVersionNumber(); String getModuleVersionNumber();
/** /**
* Queries the factory to determine if it provides user interface panels to * Queries the factory to determine if it provides a user interface panel to
* configure resources to be used by instances of the family of ingest * allow a user to change settings that are used by all instances of the
* modules the factory creates. For example, the core hash lookup ingest * family of ingest modules the factory creates. For example, the Autopsy
* module factory provides resource configuration panels to import and * core hash lookup ingest module factory provides a global settings panel
* create hash databases. The hash databases are then enabled or disabled * to import and create hash databases. The hash databases are then enabled
* per ingest job using ingest job options panels. If the module family does * or disabled per ingest job using an ingest job settings panel. If the
* not have a resources configuration, the factory should extend * module family does not have global settings, the factory may extend
* IngestModuleFactoryAdapter to get an implementation of this method that * IngestModuleFactoryAdapter to get an implementation of this method that
* returns false. * returns false.
* *
* @return True if the factory provides resource configuration panels. * @return True if the factory provides a global settings panel.
*/ */
boolean hasGlobalSettingsPanel(); boolean hasGlobalSettingsPanel();
/** /**
* Gets a user interface panel that can be used to configure resources for * Gets a user interface panel that allows a user to change settings that
* instances of the family of ingest modules the factory creates. For * are used by all instances of the family of ingest modules the factory
* example, the core hash lookup ingest module factory provides a resource * creates. For example, the Autopsy core hash lookup ingest module factory
* configuration panel to import and create hash databases. The imported * provides a global settings panel to import and create hash databases. The
* hash databases are then enabled or disabled per ingest job using ingest * imported hash databases are then enabled or disabled per ingest job using
* options panels. If the module family does not have a resources * ingest an ingest job settings panel. If the module family does not have a
* configuration, the factory should extend IngestModuleFactoryAdapter to * global settings, the factory may extend IngestModuleFactoryAdapter to get
* get an implementation of this method that throws an * an implementation of this method that throws an
* UnsupportedOperationException. * UnsupportedOperationException.
* <p>
* IMPORTANT: The ingest framework assumes that ingest module factories are
* stateless to support context-sensitive use of the factory, with the
* ingest framework managing context switching and the persistence of
* resource configurations and per ingest job options. A factory should not
* retain references to the resources configuration panels it creates.
* *
* @param resourcesConfig A resources configuration with which to initialize * @return A global settings panel.
* the panel.
* @return A user interface panel for configuring ingest module resources.
*/ */
IngestModuleGlobalSetttingsPanel getGlobalSettingsPanel(); IngestModuleGlobalSetttingsPanel getGlobalSettingsPanel();
/** /**
* Gets the default per ingest job options for instances of the family of * Gets the default per ingest job settings for instances of the family of
* ingest modules the factory creates. For example, the core hash lookup * ingest modules the factory creates. For example, the Autopsy core hash
* ingest modules family has a resources configuration consisting of hash * lookup ingest modules family uses hash databases imported or created
* databases, all of which are enabled by default for an ingest job. If the * using its global settings panel. All of the hash databases are enabled by
* module family does not have per ingest job options, the factory should * default for an ingest job. If the module family does not have per ingest
* extend IngestModuleFactoryAdapter to get an implementation of this method * job settings, the factory may extend IngestModuleFactoryAdapter to get an
* that returns an instance of the NoIngestJobOptions class. * implementation of this method that returns an instance of the
* NoIngestModuleJobSettings class.
* *
* @return The ingest options. * @return The default ingest job settings.
*/ */
IngestModuleIngestJobSettings getDefaultModuleSettings(); IngestModuleIngestJobSettings getDefaultIngestJobSettings();
/** /**
* Queries the factory to determine if it provides user interface panels to * Queries the factory to determine if it provides user a interface panel to
* set per ingest job options for instances of the family of ingest modules * allow a user to make per ingest job settings for instances of the family
* the factory creates. For example, the core hash lookup ingest module * of ingest modules the factory creates. For example, the Autopsy core hash
* factory provides ingest options panels to enable or disable hash * lookup ingest module factory provides an ingest job settings panels to
* databases per ingest job. If the module family does not have per ingest * enable or disable hash databases per ingest job. If the module family
* job options, the factory should extend IngestModuleFactoryAdapter to get * does not have per ingest job settings, the factory may extend
* an implementation of this method that returns false. * IngestModuleFactoryAdapter to get an implementation of this method that
* returns false.
* *
* @return True if the factory provides ingest job options panels. * @return True if the factory provides ingest job settings panels.
*/ */
boolean hasModuleSettingsPanel(); boolean hasIngestJobSettingsPanel();
/** /**
* Gets a user interface panel that can be used to set per ingest job * Gets a user interface panel that can be used to set per ingest job
* options for instances of the family of ingest modules the factory * settings for instances of the family of ingest modules the factory
* creates. For example, the core hash lookup ingest module factory provides * creates. For example, the core hash lookup ingest module factory provides
* ingest options panels to enable or disable hash databases per ingest job. * an ingest job settings panel to enable or disable hash databases per
* If the module family does not have ingest job options, the factory should * ingest job. If the module family does not have per ingest job settings,
* extend IngestModuleFactoryAdapter to get an implementation of this method * the factory may extend IngestModuleFactoryAdapter to get an
* that throws an UnsupportedOperationException. * implementation of this method that throws an
* <p> * UnsupportedOperationException.
* IMPORTANT: The ingest framework assumes that ingest module factories are
* stateless to support context-sensitive use of the factory. The ingest
* framework is responsible for managing context switching and the
* persistence of resource configurations and per ingest job options. A
* factory should not retain references to the ingest job options panels it
* creates.
* *
* @param resourcesConfig * @param setting Per ingest job settings to initialize the panel.
* @param ingestOptions Per ingest job options to initialize the panel. * @return An ingest job settings panel.
* @return A user interface panel.
*/ */
IngestModuleIngestJobSettingsPanel getModuleSettingsPanel(IngestModuleIngestJobSettings settings); IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings);
/** /**
* Queries the factory to determine if it is capable of creating file ingest * Queries the factory to determine if it is capable of creating data source
* modules. * ingest modules. If the module family does not include data source ingest
* modules, the factory may extend IngestModuleFactoryAdapter to get an
* implementation of this method that returns false.
* *
* @return True if the factory can create file ingest modules. * @return True if the factory can create data source ingest modules.
*/ */
boolean isDataSourceIngestModuleFactory(); boolean isDataSourceIngestModuleFactory();
/** /**
* Creates a data source ingest module instance. * Creates a data source ingest module instance.
* <p> * <p>
* IMPORTANT: The factory should be stateless to support context-sensitive * Autopsy will generally use the factory to several instances of each type
* use of the factory. The ingest framework is responsible for managing * of module for each ingest job it performs. Completing an ingest job
* context switching and the persistence of resource configurations and per * entails processing a single data source (e.g., a disk image) and all of
* ingest job options. A factory should not retain references to the data * the files from the data source, including files extracted from archives
* source ingest module instances it creates. * and any unallocated space (made to look like a series of files). The data
* source is passed through one or more pipelines of data source ingest
* modules. The files are passed through one or more pipelines of file
* ingest modules.
* <p> * <p>
* IMPORTANT: The ingest framework will create one or more data source * The ingest framework may use multiple threads to complete an ingest job,
* ingest module instances for each ingest job it performs. The ingest * but it is guaranteed that there will be no more than one module instance
* framework may use multiple threads to complete an ingest job, but it is * per thread. However, if the module instances must share resources, the
* guaranteed that there will be no more than one module instance per * modules are responsible for synchronizing access to the shared resources
* thread. However, if these instances must share resources, the modules are * and doing reference counting as required to release those resources
* responsible for synchronizing access to the shared resources and doing * correctly. Also, more than one ingest job may be in progress at any given
* reference counting as required to release those resources correctly. * time. This must also be taken into consideration when sharing resources
* between module instances. modules.
* <p>
* If the module family does not include data source ingest modules, the
* factory may extend IngestModuleFactoryAdapter to get an implementation of
* this method that throws an UnsupportedOperationException.
* *
* @param ingestOptions The ingest options for the module instance. * @param settings The settings for the ingest job.
* @return A data source ingest module instance. * @return A data source ingest module instance.
*/ */
DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings); DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings);
/** /**
* Queries the factory to determine if it is capable of creating file ingest * Queries the factory to determine if it is capable of creating file ingest
* module instances. * modules. If the module family does not include file ingest modules, the
* factory may extend IngestModuleFactoryAdapter to get an implementation of
* this method that returns false.
* *
* @return True if the factory can create file ingest module instances. * @return True if the factory can create file ingest modules.
*/ */
boolean isFileIngestModuleFactory(); boolean isFileIngestModuleFactory();
/** /**
* Creates a file ingest module instance. * Creates a file ingest module instance.
* <p> * <p>
* IMPORTANT: The factory should be stateless to support context-sensitive * Autopsy will generally use the factory to several instances of each type
* use of the factory. The ingest framework is responsible for managing * of module for each ingest job it performs. Completing an ingest job
* context switching and the persistence of resource configurations and per * entails processing a single data source (e.g., a disk image) and all of
* ingest job options. A factory should not retain references to the file * the files from the data source, including files extracted from archives
* ingest module instances it creates. * and any unallocated space (made to look like a series of files). The data
* source is passed through one or more pipelines of data source ingest
* modules. The files are passed through one or more pipelines of file
* ingest modules.
* <p> * <p>
* IMPORTANT: The ingest framework will create one or more file ingest * The ingest framework may use multiple threads to complete an ingest job,
* module instances for each ingest job it performs. The ingest framework * but it is guaranteed that there will be no more than one module instance
* may use multiple threads to complete an ingest job, but it is guaranteed * per thread. However, if the module instances must share resources, the
* that there will be no more than one module instance per thread. However, * modules are responsible for synchronizing access to the shared resources
* if these instances must share resources, the modules are responsible for * and doing reference counting as required to release those resources
* synchronizing access to the shared resources and doing reference counting * correctly. Also, more than one ingest job may be in progress at any given
* as required to release those resources correctly. * time. This must also be taken into consideration when sharing resources
* between module instances. modules.
* <p>
* If the module family does not include file ingest modules, the factory
* may extend IngestModuleFactoryAdapter to get an implementation of this
* method that throws an UnsupportedOperationException.
* *
* @param ingestOptions The ingest options for the module instance. * @param settings The settings for the ingest job.
* @return A file ingest module instance. * @return A file ingest module instance.
*/ */
FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings); FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings);

View File

@ -44,17 +44,17 @@ public abstract class IngestModuleFactoryAdapter implements IngestModuleFactory
} }
@Override @Override
public IngestModuleIngestJobSettings getDefaultModuleSettings() { public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
return new NoIngestModuleSettings(); return new NoIngestModuleIngestJobSettings();
} }
@Override @Override
public boolean hasModuleSettingsPanel() { public boolean hasIngestJobSettingsPanel() {
return false; return false;
} }
@Override @Override
public IngestModuleIngestJobSettingsPanel getModuleSettingsPanel(IngestModuleIngestJobSettings ingestOptions) { public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings ingestOptions) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.ingest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
@ -27,7 +28,7 @@ import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
/** /**
* Looks up loaded ingest module factories using the NetBean global lookup. * Looks up loaded ingest module factories using the NetBeans global lookup.
*/ */
final class IngestModuleFactoryLoader { final class IngestModuleFactoryLoader {
@ -45,18 +46,55 @@ final class IngestModuleFactoryLoader {
} }
synchronized List<IngestModuleFactory> getIngestModuleFactories() { synchronized List<IngestModuleFactory> getIngestModuleFactories() {
List<IngestModuleFactory> moduleFactories = new ArrayList<>(); // Discover the ingest module factories, making sure that there are no
// duplicate module display names. The duplicates requirement could be
// eliminated if the enabled/disabled modules setting was by factory
// class name instead of module display name. Also note that that we are
// temporarily hard-coding ordering of module factories until the
// module configuration file is reworked, so the discovered factories
// are initially mapped by class name.
HashSet<String> moduleDisplayNames = new HashSet<>(); HashSet<String> moduleDisplayNames = new HashSet<>();
HashMap<String, IngestModuleFactory> moduleFactoriesByClass = new HashMap<>();
Collection<? extends IngestModuleFactory> factories = Lookup.getDefault().lookupAll(IngestModuleFactory.class); Collection<? extends IngestModuleFactory> factories = Lookup.getDefault().lookupAll(IngestModuleFactory.class);
for (IngestModuleFactory factory : factories) { for (IngestModuleFactory factory : factories) {
logger.log(Level.INFO, "Found ingest module factory: name = {0}, version = {1}", new Object[]{factory.getModuleDisplayName(), factory.getModuleVersionNumber()}); logger.log(Level.INFO, "Found ingest module factory: name = {0}, version = {1}", new Object[]{factory.getModuleDisplayName(), factory.getModuleVersionNumber()});
if (!moduleDisplayNames.contains(factory.getModuleDisplayName())) { if (!moduleDisplayNames.contains(factory.getModuleDisplayName())) {
moduleFactories.add(factory); moduleFactoriesByClass.put(factory.getClass().getCanonicalName(), factory);
moduleDisplayNames.add(factory.getModuleDisplayName()); moduleDisplayNames.add(factory.getModuleDisplayName());
} else { } else {
// Not popping up a message box to keep this class UI-indepdent.
logger.log(Level.SEVERE, "Found duplicate ingest module display name, discarding ingest module factory (name = {0}", new Object[]{factory.getModuleDisplayName(), factory.getModuleVersionNumber()}); logger.log(Level.SEVERE, "Found duplicate ingest module display name, discarding ingest module factory (name = {0}", new Object[]{factory.getModuleDisplayName(), factory.getModuleVersionNumber()});
} }
} }
return new ArrayList<>(moduleFactories);
// Kick out the sample modules factory.
moduleFactoriesByClass.remove("org.sleuthkit.autopsy.examples.SampleIngestModuleFactory");
// Do the core ingest module ordering hack described above.
ArrayList<String> coreModuleOrdering = new ArrayList<String>() {{
add("org.sleuthkit.autopsy.recentactivity.RecentActivityExtracterModuleFactory");
add("org.sleuthkit.autopsy.ewfverify.EwfVerifierModuleFactory");
add("org.sleuthkit.autopsy.hashdatabase.HashLookupModuleFactory");
add("org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdModuleFactory");
add("org.sleuthkit.autopsy.modules.sevenzip.ArchiveFileExtractorModuleFactory");
add("org.sleuthkit.autopsy.modules.exif.ExifParserModuleFactory");
add("org.sleuthkit.autopsy.keywordsearch.KeywordSearchModuleFactory");
add("org.sleuthkit.autopsy.thunderbirdparser.EmailParserModuleFactory");
add("org.sleuthkit.autopsy.fileextmismatch.FileExtMismatchDetectorModuleFactory");
}};
List<IngestModuleFactory> orderedModuleFactories = new ArrayList<>();
for (String className : coreModuleOrdering) {
IngestModuleFactory coreFactory = moduleFactoriesByClass.remove(className);
if (coreFactory != null) {
orderedModuleFactories.add(coreFactory);
}
}
// Add in any non-core factories discovered. Order is not guaranteed!
for (IngestModuleFactory nonCoreFactory : moduleFactoriesByClass.values()) {
orderedModuleFactories.add(nonCoreFactory);
}
return orderedModuleFactories;
} }
} }

View File

@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.ingest;
import javax.swing.JPanel; import javax.swing.JPanel;
/** /**
* Base class for ingest module resources configuration panels. * Base class for ingest module global settings panels.
*/ */
public abstract class IngestModuleGlobalSetttingsPanel extends JPanel { public abstract class IngestModuleGlobalSetttingsPanel extends JPanel {

View File

@ -0,0 +1,59 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011 - 2013 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.ingest;
import java.util.HashMap;
/**
* A utility class that modules can use to keep track of whether they are the
* first/last instance for a particular job.
*
* An instance of this should be static in your module class.
*/
public class IngestModuleReferenceCounter {
// Maps a JobId to the count of instances
private HashMap<Long, Long> moduleRefCount = new HashMap<>();
public synchronized long get(long jobId) {
return moduleRefCount.get(jobId);
}
public synchronized long incrementAndGet(long jobId) {
long count = moduleRefCount.containsKey(jobId) ? moduleRefCount.get(jobId) : 0;
long nextCount = count + 1;
moduleRefCount.put(jobId, nextCount);
return nextCount;
}
public synchronized long decrementAndGet(long jobId) {
if (moduleRefCount.containsKey(jobId)) {
long count = moduleRefCount.get(jobId);
if (--count == 0) {
moduleRefCount.remove(jobId);
} else {
moduleRefCount.put(jobId, count);
}
return count;
} else {
return -1;
}
}
}

View File

@ -50,11 +50,11 @@ final class IngestModuleTemplate {
} }
boolean hasModuleSettingsPanel() { boolean hasModuleSettingsPanel() {
return moduleFactory.hasModuleSettingsPanel(); return moduleFactory.hasIngestJobSettingsPanel();
} }
IngestModuleIngestJobSettingsPanel getModuleSettingsPanel() { IngestModuleIngestJobSettingsPanel getModuleSettingsPanel() {
return moduleFactory.getModuleSettingsPanel(settings); return moduleFactory.getIngestJobSettingsPanel(settings);
} }
boolean hasGlobalSettingsPanel() { boolean hasGlobalSettingsPanel() {

View File

@ -151,7 +151,7 @@ public final class IngestMonitor {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
final IngestManager manager = IngestManager.getDefault(); final IngestManager manager = IngestManager.getInstance();
//runs checks only if ingest is running //runs checks only if ingest is running
if (manager.isIngestRunning() == false) { if (manager.isIngestRunning() == false) {
@ -163,10 +163,10 @@ public final class IngestMonitor {
if (checkDiskSpace() == false) { if (checkDiskSpace() == false) {
//stop ingest if running //stop ingest if running
final String diskPath = root.getAbsolutePath(); final String diskPath = root.getAbsolutePath();
MONITOR_LOGGER.log(Level.SEVERE, "Stopping ingest due to low disk space on disk " + diskPath); MONITOR_LOGGER.log(Level.SEVERE, "Stopping ingest due to low disk space on disk {0}", diskPath);
logger.log(Level.SEVERE, "Stopping ingest due to low disk space on disk " + diskPath); logger.log(Level.SEVERE, "Stopping ingest due to low disk space on disk {0}", diskPath);
manager.stopAll(); manager.cancelIngestJobs();
IngestServices.getDefault().postMessage(IngestMessage.createManagerErrorMessage( IngestServices.getInstance().postMessage(IngestMessage.createManagerErrorMessage(
NbBundle.getMessage(this.getClass(), "IngestMonitor.mgrErrMsg.lowDiskSpace.title", diskPath), NbBundle.getMessage(this.getClass(), "IngestMonitor.mgrErrMsg.lowDiskSpace.title", diskPath),
NbBundle.getMessage(this.getClass(), "IngestMonitor.mgrErrMsg.lowDiskSpace.msg", diskPath))); NbBundle.getMessage(this.getClass(), "IngestMonitor.mgrErrMsg.lowDiskSpace.msg", diskPath)));
} }

View File

@ -24,6 +24,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -39,12 +40,15 @@ import org.w3c.dom.NodeList;
final class IngestPipelinesConfiguration { final class IngestPipelinesConfiguration {
private static final Logger logger = Logger.getLogger(IngestPipelinesConfiguration.class.getName()); private static final Logger logger = Logger.getLogger(IngestPipelinesConfiguration.class.getName());
private final static String PIPELINES_CONFIG_FILE = "pipeline_config.xml"; private static final String PIPELINE_CONFIG_FILE_VERSION_KEY = "PipelineConfigFileVersion";
private final static String PIPELINES_CONFIG_FILE_XSD = "PipelineConfigSchema.xsd"; private static final String PIPELINE_CONFIG_FILE_VERSION_NO_STRING = "1";
private static final int PIPELINE_CONFIG_FILE_VERSION_NO = 1;
private static final String PIPELINES_CONFIG_FILE = "pipeline_config.xml";
private static final String PIPELINES_CONFIG_FILE_XSD = "PipelineConfigSchema.xsd";
private static final String XML_PIPELINE_ELEM = "PIPELINE"; private static final String XML_PIPELINE_ELEM = "PIPELINE";
private static final String XML_PIPELINE_TYPE_ATTR = "type"; private static final String XML_PIPELINE_TYPE_ATTR = "type";
private final static String DATA_SOURCE_INGEST_PIPELINE_TYPE = "ImageAnalysis"; private static final String DATA_SOURCE_INGEST_PIPELINE_TYPE = "ImageAnalysis";
private final static String FILE_INGEST_PIPELINE_TYPE = "FileAnalysis"; private static final String FILE_INGEST_PIPELINE_TYPE = "FileAnalysis";
private static final String XML_MODULE_ELEM = "MODULE"; private static final String XML_MODULE_ELEM = "MODULE";
private static final String XML_MODULE_CLASS_NAME_ATTR = "location"; private static final String XML_MODULE_CLASS_NAME_ATTR = "location";
private static IngestPipelinesConfiguration instance; private static IngestPipelinesConfiguration instance;
@ -73,65 +77,73 @@ final class IngestPipelinesConfiguration {
private void readPipelinesConfigurationFile() { private void readPipelinesConfigurationFile() {
try { try {
PlatformUtil.extractResourceToUserConfigDir(IngestPipelinesConfiguration.class, PIPELINES_CONFIG_FILE); boolean overWrite;
} catch (IOException ex) { if (!ModuleSettings.settingExists(this.getClass().getSimpleName(), PIPELINE_CONFIG_FILE_VERSION_KEY)) {
logger.log(Level.SEVERE, "Error copying default pipeline configuration to user dir", ex); ModuleSettings.setConfigSetting(this.getClass().getSimpleName(), PIPELINE_CONFIG_FILE_VERSION_KEY, PIPELINE_CONFIG_FILE_VERSION_NO_STRING);
return; overWrite = true;
} } else {
int versionNumber = Integer.parseInt(ModuleSettings.getConfigSetting(this.getClass().getSimpleName(), PIPELINE_CONFIG_FILE_VERSION_KEY));
overWrite = versionNumber < PIPELINE_CONFIG_FILE_VERSION_NO;
// TODO: Migrate user edits
}
PlatformUtil.extractResourceToUserConfigDir(IngestPipelinesConfiguration.class, PIPELINES_CONFIG_FILE, overWrite);
String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + PIPELINES_CONFIG_FILE; String configFilePath = PlatformUtil.getUserConfigDirectory() + File.separator + PIPELINES_CONFIG_FILE;
Document doc = XMLUtil.loadDoc(IngestPipelinesConfiguration.class, configFilePath, PIPELINES_CONFIG_FILE_XSD); Document doc = XMLUtil.loadDoc(IngestPipelinesConfiguration.class, configFilePath, PIPELINES_CONFIG_FILE_XSD);
if (doc == null) { if (doc == null) {
return; return;
}
Element rootElement = doc.getDocumentElement();
if (rootElement == null) {
logger.log(Level.SEVERE, "Invalid pipelines config file");
return;
}
NodeList pipelineElements = rootElement.getElementsByTagName(XML_PIPELINE_ELEM);
int numPipelines = pipelineElements.getLength();
if (numPipelines < 1 || numPipelines > 2) {
logger.log(Level.SEVERE, "Invalid pipelines config file");
return;
}
List<String> pipelineConfig = null;
for (int pipelineNum = 0; pipelineNum < numPipelines; ++pipelineNum) {
Element pipelineElement = (Element) pipelineElements.item(pipelineNum);
String pipelineTypeAttr = pipelineElement.getAttribute(XML_PIPELINE_TYPE_ATTR);
if (pipelineTypeAttr != null) {
switch (pipelineTypeAttr) {
case DATA_SOURCE_INGEST_PIPELINE_TYPE:
pipelineConfig = dataSourceIngestPipelineConfig;
break;
case FILE_INGEST_PIPELINE_TYPE:
pipelineConfig = fileIngestPipelineConfig;
break;
default:
logger.log(Level.SEVERE, "Invalid pipelines config file");
return;
}
} }
// Create an ordered list of class names. The sequence of class Element rootElement = doc.getDocumentElement();
// names defines the sequence of modules in the pipeline. if (rootElement == null) {
if (pipelineConfig != null) { logger.log(Level.SEVERE, "Invalid pipelines config file");
NodeList modulesElems = pipelineElement.getElementsByTagName(XML_MODULE_ELEM); return;
int numModules = modulesElems.getLength(); }
if (numModules == 0) {
break; NodeList pipelineElements = rootElement.getElementsByTagName(XML_PIPELINE_ELEM);
int numPipelines = pipelineElements.getLength();
if (numPipelines < 1 || numPipelines > 2) {
logger.log(Level.SEVERE, "Invalid pipelines config file");
return;
}
List<String> pipelineConfig = null;
for (int pipelineNum = 0; pipelineNum < numPipelines; ++pipelineNum) {
Element pipelineElement = (Element) pipelineElements.item(pipelineNum);
String pipelineTypeAttr = pipelineElement.getAttribute(XML_PIPELINE_TYPE_ATTR);
if (pipelineTypeAttr != null) {
switch (pipelineTypeAttr) {
case DATA_SOURCE_INGEST_PIPELINE_TYPE:
pipelineConfig = dataSourceIngestPipelineConfig;
break;
case FILE_INGEST_PIPELINE_TYPE:
pipelineConfig = fileIngestPipelineConfig;
break;
default:
logger.log(Level.SEVERE, "Invalid pipelines config file");
return;
}
} }
for (int moduleNum = 0; moduleNum < numModules; ++moduleNum) {
Element moduleElement = (Element) modulesElems.item(moduleNum); // Create an ordered list of class names. The sequence of class
final String moduleClassName = moduleElement.getAttribute(XML_MODULE_CLASS_NAME_ATTR); // names defines the sequence of modules in the pipeline.
if (moduleClassName != null) { if (pipelineConfig != null) {
pipelineConfig.add(moduleClassName); NodeList modulesElems = pipelineElement.getElementsByTagName(XML_MODULE_ELEM);
int numModules = modulesElems.getLength();
if (numModules == 0) {
break;
}
for (int moduleNum = 0; moduleNum < numModules; ++moduleNum) {
Element moduleElement = (Element) modulesElems.item(moduleNum);
final String moduleClassName = moduleElement.getAttribute(XML_MODULE_CLASS_NAME_ATTR);
if (moduleClassName != null) {
pipelineConfig.add(moduleClassName);
}
} }
} }
} }
} catch (IOException ex) {
logger.log(Level.SEVERE, "Error copying default pipeline configuration to user dir", ex);
} }
} }
} }

View File

@ -19,11 +19,9 @@
package org.sleuthkit.autopsy.ingest; package org.sleuthkit.autopsy.ingest;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**
@ -33,12 +31,10 @@ import org.sleuthkit.datamodel.SleuthkitCase;
*/ */
public final class IngestServices { public final class IngestServices {
private static final Logger logger = Logger.getLogger(IngestServices.class.getName()); private static IngestServices instance = null;
private IngestManager manager; private final IngestManager manager = IngestManager.getInstance();
private static IngestServices instance;
private IngestServices() { private IngestServices() {
this.manager = IngestManager.getDefault();
} }
/** /**
@ -46,7 +42,7 @@ public final class IngestServices {
* *
* @return The ingest services singleton. * @return The ingest services singleton.
*/ */
public static synchronized IngestServices getDefault() { public static synchronized IngestServices getInstance() {
if (instance == null) { if (instance == null) {
instance = new IngestServices(); instance = new IngestServices();
} }
@ -71,7 +67,7 @@ public final class IngestServices {
return Case.getCurrentCase().getSleuthkitCase(); return Case.getCurrentCase().getSleuthkitCase();
} }
/** /**
* Get a logger that incorporates the display name of an ingest module in * Get a logger that incorporates the display name of an ingest module in
* messages written to the Autopsy log files. * messages written to the Autopsy log files.
* *
@ -91,20 +87,9 @@ public final class IngestServices {
manager.postIngestMessage(message); manager.postIngestMessage(message);
} }
/**
* Fire module event to notify registered module event listeners
*
* @param eventType the event type, defined in
* IngestManager.IngestManagerEvents
* @param moduleName the module name
*/
public void fireModuleEvent(String eventType, String moduleName) {
IngestManager.fireModuleEvent(eventType, moduleName);
}
/** /**
* Fire module data event to notify registered module data event listeners * Fire module data event to notify registered module data event listeners
* that there is new data of a given type from a module * that there is new data of a given type from a module.
* *
* @param moduleDataEvent module data event, encapsulating blackboard * @param moduleDataEvent module data event, encapsulating blackboard
* artifact data * artifact data
@ -135,8 +120,9 @@ public final class IngestServices {
return manager.getFreeDiskSpace(); return manager.getFreeDiskSpace();
} }
/** /**
* Gets a specific name/value configuration setting for a module * Gets a specific name/value configuration setting for a module
*
* @param moduleName moduleName identifier unique to that module * @param moduleName moduleName identifier unique to that module
* @param settingName setting name to retrieve * @param settingName setting name to retrieve
* @return setting value for the module / setting name, or null if not found * @return setting value for the module / setting name, or null if not found
@ -147,6 +133,7 @@ public final class IngestServices {
/** /**
* Sets a specific name/value configuration setting for a module * Sets a specific name/value configuration setting for a module
*
* @param moduleName moduleName identifier unique to that module * @param moduleName moduleName identifier unique to that module
* @param settingName setting name to set * @param settingName setting name to set
* @param settingVal setting value to set * @param settingVal setting value to set
@ -157,20 +144,24 @@ public final class IngestServices {
/** /**
* Gets all name/value configuration settings for a module * Gets all name/value configuration settings for a module
*
* @param moduleName moduleName identifier unique to that module * @param moduleName moduleName identifier unique to that module
* @return settings for the module / setting name * @return settings for the module / setting name
*/ */
public Map<String,String> getConfigSettings(String moduleName) { public Map<String, String> getConfigSettings(String moduleName) {
return ModuleSettings.getConfigSettings(moduleName); return ModuleSettings.getConfigSettings(moduleName);
} }
/** /**
* Sets all name/value configuration setting for a module. Names not in the list will have settings preserved. * Sets all name/value configuration setting for a module. Names not in the
* list will have settings preserved.
*
* @param moduleName moduleName identifier unique to that module * @param moduleName moduleName identifier unique to that module
* @param settings settings to set and replace old settings, keeping settings not specified in the map. * @param settings settings to set and replace old settings, keeping
* settings not specified in the map.
* *
*/ */
public void setConfigSettings(String moduleName, Map<String,String>settings) { public void setConfigSettings(String moduleName, Map<String, String> settings) {
ModuleSettings.setConfigSettings(moduleName, settings); ModuleSettings.setConfigSettings(moduleName, settings);
} }
} }

View File

@ -46,7 +46,7 @@ public class Installer extends ModuleInstall {
Logger logger = Logger.getLogger(Installer.class.getName()); Logger logger = Logger.getLogger(Installer.class.getName());
logger.log(Level.INFO, "Initializing ingest manager"); logger.log(Level.INFO, "Initializing ingest manager");
final IngestManager manager = IngestManager.getDefault(); final IngestManager manager = IngestManager.getInstance();
WindowManager.getDefault().invokeWhenUIReady(new Runnable() { WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
@Override @Override
public void run() { public void run() {

View File

@ -88,7 +88,4 @@ public class ModuleDataEvent extends ChangeEvent {
public String getModuleName() { public String getModuleName() {
return moduleName; return moduleName;
} }
} }

View File

@ -22,7 +22,7 @@ package org.sleuthkit.autopsy.ingest;
* Implementation of the IngestModuleOptions interface for use by ingest modules * Implementation of the IngestModuleOptions interface for use by ingest modules
* that do not have per ingest job options. * that do not have per ingest job options.
*/ */
public final class NoIngestModuleSettings implements IngestModuleIngestJobSettings { public final class NoIngestModuleIngestJobSettings implements IngestModuleIngestJobSettings {
private final String setting = "None"; private final String setting = "None";

View File

@ -37,19 +37,19 @@ import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
/** /**
* Dialog box that allows ingest modules to be run on a data source. Used * Dialog box that allows ingest modules to be run on a data source that has
* outside of the wizards. * already been added to a case.
*/ */
public final class IngestDialog extends JDialog { public final class RunIngestModulesDialog extends JDialog {
private static final String TITLE = NbBundle.getMessage(IngestDialog.class, "IngestDialog.title.text"); private static final String TITLE = NbBundle.getMessage(RunIngestModulesDialog.class, "IngestDialog.title.text");
private static Dimension DIMENSIONS = new Dimension(500, 300); private static Dimension DIMENSIONS = new Dimension(500, 300);
private List<Content> dataSources = new ArrayList<>(); private List<Content> dataSources = new ArrayList<>();
private IngestJobLauncher ingestJobLauncher; private IngestJobLauncher ingestJobLauncher;
public IngestDialog(JFrame frame, String title, boolean modal) { public RunIngestModulesDialog(JFrame frame, String title, boolean modal) {
super(frame, title, modal); super(frame, title, modal);
ingestJobLauncher = new IngestJobLauncher(IngestDialog.class.getCanonicalName()); ingestJobLauncher = new IngestJobLauncher(RunIngestModulesDialog.class.getCanonicalName());
List<String> messages = ingestJobLauncher.getIngestJobConfigWarnings(); List<String> messages = ingestJobLauncher.getIngestJobConfigWarnings();
if (messages.isEmpty() == false) { if (messages.isEmpty() == false) {
StringBuilder warning = new StringBuilder(); StringBuilder warning = new StringBuilder();
@ -60,7 +60,7 @@ public final class IngestDialog extends JDialog {
} }
} }
public IngestDialog() { public RunIngestModulesDialog() {
this(new JFrame(TITLE), TITLE, true); this(new JFrame(TITLE), TITLE, true);
} }

View File

@ -4,12 +4,12 @@ Contains only the core ingest modules that ship with Autopsy -->
<PIPELINE_CONFIG> <PIPELINE_CONFIG>
<PIPELINE type="FileAnalysis"> <PIPELINE type="FileAnalysis">
<MODULE order="1" type="plugin" location="org.sleuthkit.autopsy.hashdatabase.HashDbIngestModule" arguments="" /> <MODULE order="1" type="plugin" location="org.sleuthkit.autopsy.hashdatabase.HashDbIngestModule" arguments="" />
<MODULE order="2" type="plugin" location="org.sleuthkit.autopsy.filetypeid.FileTypeIdIngestModule" arguments=""/> <MODULE order="2" type="plugin" location="org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdIngestModule" arguments=""/>
<MODULE order="3" type="plugin" location="org.sleuthkit.autopsy.sevenzip.SevenZipIngestModule" arguments="" /> <MODULE order="3" type="plugin" location="org.sleuthkit.autopsy.modules.sevenzip.SevenZipIngestModule" arguments="" />
<MODULE order="4" type="plugin" location="org.sleuthkit.autopsy.exifparser.ExifParserFileIngestModule"/> <MODULE order="4" type="plugin" location="org.sleuthkit.autopsy.modules.exifparser.ExifParserFileIngestModule"/>
<MODULE order="5" type="plugin" location="org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule"/> <MODULE order="5" type="plugin" location="org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule"/>
<MODULE order="6" type="plugin" location="org.sleuthkit.autopsy.thunderbirdparser.ThunderbirdMboxFileIngestModule" arguments=""/> <MODULE order="6" type="plugin" location="org.sleuthkit.autopsy.thunderbirdparser.ThunderbirdMboxFileIngestModule" arguments=""/>
<MODULE order="7" type="plugin" location="org.sleuthkit.autopsy.fileextmismatch.FileExtMismatchIngestModule" arguments=""/> <MODULE order="7" type="plugin" location="org.sleuthkit.autopsy.modules.fileextmismatch.FileExtMismatchIngestModule" arguments=""/>
</PIPELINE> </PIPELINE>
<PIPELINE type="ImageAnalysis"> <PIPELINE type="ImageAnalysis">

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.exifparser; package org.sleuthkit.autopsy.modules.exif;
import com.drew.imaging.ImageMetadataReader; import com.drew.imaging.ImageMetadataReader;
import com.drew.imaging.ImageProcessingException; import com.drew.imaging.ImageProcessingException;
@ -32,13 +32,16 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Date; import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.ImageUtils; import org.sleuthkit.autopsy.coreutils.ImageUtils;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestModuleAdapter; import org.sleuthkit.autopsy.ingest.IngestModuleAdapter;
import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
@ -56,13 +59,22 @@ import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
public final class ExifParserFileIngestModule extends IngestModuleAdapter implements FileIngestModule { public final class ExifParserFileIngestModule extends IngestModuleAdapter implements FileIngestModule {
private static final Logger logger = Logger.getLogger(ExifParserFileIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(ExifParserFileIngestModule.class.getName());
private final IngestServices services = IngestServices.getDefault(); private final IngestServices services = IngestServices.getInstance();
private int filesProcessed = 0; private AtomicInteger filesProcessed = new AtomicInteger(0);
private boolean filesToFire = false; private volatile boolean filesToFire = false;
private long jobId;
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
ExifParserFileIngestModule() { ExifParserFileIngestModule() {
} }
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
jobId = context.getJobId();
refCounter.incrementAndGet(jobId);
}
@Override @Override
public ProcessResult process(AbstractFile content) { public ProcessResult process(AbstractFile content) {
//skip unalloc //skip unalloc
@ -76,8 +88,8 @@ public final class ExifParserFileIngestModule extends IngestModuleAdapter implem
} }
// update the tree every 1000 files if we have EXIF data that is not being being displayed // update the tree every 1000 files if we have EXIF data that is not being being displayed
filesProcessed++; final int filesProcessedValue = filesProcessed.incrementAndGet();
if ((filesToFire) && (filesProcessed % 1000 == 0)) { if ((filesToFire) && (filesProcessedValue % 1000 == 0)) {
services.fireModuleDataEvent(new ModuleDataEvent(ExifParserModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)); services.fireModuleDataEvent(new ModuleDataEvent(ExifParserModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF));
filesToFire = false; filesToFire = false;
} }
@ -187,9 +199,12 @@ public final class ExifParserFileIngestModule extends IngestModuleAdapter implem
@Override @Override
public void shutDown(boolean ingestJobCancelled) { public void shutDown(boolean ingestJobCancelled) {
if (filesToFire) { // We only need to check for this final event on the last module per job
//send the final new data event if (refCounter.decrementAndGet(jobId) == 0) {
services.fireModuleDataEvent(new ModuleDataEvent(ExifParserModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)); if (filesToFire) {
//send the final new data event
services.fireModuleDataEvent(new ModuleDataEvent(ExifParserModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF));
}
} }
} }
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.exifparser; package org.sleuthkit.autopsy.modules.exif;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.coreutils.Version; import org.sleuthkit.autopsy.coreutils.Version;

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;

View File

@ -34,7 +34,6 @@ FileExtMismatchIngestModule.complete.totalFiles=Total Files Processed
FileExtMismatchIngestModule.complete.svcMsg.text=File Extension Mismatch Results FileExtMismatchIngestModule.complete.svcMsg.text=File Extension Mismatch Results
FileExtMismatchOptionsPanelController.moduleErr=Module Error FileExtMismatchOptionsPanelController.moduleErr=Module Error
FileExtMismatchOptionsPanelController.moduleErr.msg=A module caused an error listening to FileExtMismatchOptionsPanelController updates. See log to determine which module. Some data could be incomplete. FileExtMismatchOptionsPanelController.moduleErr.msg=A module caused an error listening to FileExtMismatchOptionsPanelController updates. See log to determine which module. Some data could be incomplete.
FileExtMismatchModuleSettingsPanel.skipKnownFilesCheckbox.text=Skip known files (NSRL)
FileExtMismatchModuleSettingsPanel.skipTextPlain.text=Skip text files FileExtMismatchModuleSettingsPanel.skipTextPlain.text=Skip text files
FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=Skip files without extensions FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text=Skip files without extensions
FileExtMismatchSettingsPanel.addTypeButton.text=Add Type FileExtMismatchSettingsPanel.addTypeButton.text=Add Type

View File

@ -18,7 +18,7 @@
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -50,7 +50,7 @@ public class FileExtMismatchContextMenuActionsProvider implements ContextMenuAct
ArrayList<Action> actions = new ArrayList<>(); ArrayList<Action> actions = new ArrayList<>();
// Ignore if file ingest is in progress. // Ignore if file ingest is in progress.
if (!IngestManager.getDefault().isIngestRunning()) { if (!IngestManager.getInstance().isIngestRunning()) {
final Collection<? extends BlackboardArtifact> selectedArts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class); final Collection<? extends BlackboardArtifact> selectedArts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
@ -57,17 +57,17 @@ public class FileExtMismatchDetectorModuleFactory extends IngestModuleFactoryAda
} }
@Override @Override
public IngestModuleIngestJobSettings getDefaultModuleSettings() { public IngestModuleIngestJobSettings getDefaultIngestJobSettings() {
return new FileExtMismatchDetectorModuleSettings(); return new FileExtMismatchDetectorModuleSettings();
} }
@Override @Override
public boolean hasModuleSettingsPanel() { public boolean hasIngestJobSettingsPanel() {
return true; return true;
} }
@Override @Override
public IngestModuleIngestJobSettingsPanel getModuleSettingsPanel(IngestModuleIngestJobSettings settings) { public IngestModuleIngestJobSettingsPanel getIngestJobSettingsPanel(IngestModuleIngestJobSettings settings) {
assert settings instanceof FileExtMismatchDetectorModuleSettings; assert settings instanceof FileExtMismatchDetectorModuleSettings;
if (!(settings instanceof FileExtMismatchDetectorModuleSettings)) { if (!(settings instanceof FileExtMismatchDetectorModuleSettings)) {
throw new IllegalArgumentException("Expected settings argument to be instanceof FileExtMismatchDetectorModuleSettings"); throw new IllegalArgumentException("Expected settings argument to be instanceof FileExtMismatchDetectorModuleSettings");

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
@ -25,7 +25,6 @@ import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
*/ */
final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJobSettings { final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJobSettings {
private boolean skipKnownFiles = false;
private boolean skipFilesWithNoExtension = true; private boolean skipFilesWithNoExtension = true;
private boolean skipFilesWithTextPlainMimeType = false; private boolean skipFilesWithTextPlainMimeType = false;
@ -33,19 +32,10 @@ final class FileExtMismatchDetectorModuleSettings implements IngestModuleIngestJ
} }
FileExtMismatchDetectorModuleSettings(boolean skipKnownFiles, boolean skipFilesWithNoExtension, boolean skipFilesWithTextPlainMimeType) { FileExtMismatchDetectorModuleSettings(boolean skipKnownFiles, boolean skipFilesWithNoExtension, boolean skipFilesWithTextPlainMimeType) {
this.skipKnownFiles = skipKnownFiles;
this.skipFilesWithNoExtension = skipFilesWithNoExtension; this.skipFilesWithNoExtension = skipFilesWithNoExtension;
this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType; this.skipFilesWithTextPlainMimeType = skipFilesWithTextPlainMimeType;
} }
void setSkipKnownFiles(boolean enabled) {
skipKnownFiles = enabled;
}
boolean skipKnownFiles() {
return skipKnownFiles;
}
void setSkipFilesWithNoExtension(boolean enabled) { void setSkipFilesWithNoExtension(boolean enabled) {
skipFilesWithNoExtension = enabled; skipFilesWithNoExtension = enabled;
} }

View File

@ -16,13 +16,14 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -32,13 +33,13 @@ import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent; import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskData.FileKnown;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
/** /**
@ -47,12 +48,13 @@ import org.sleuthkit.datamodel.TskException;
public class FileExtMismatchIngestModule extends IngestModuleAdapter implements FileIngestModule { public class FileExtMismatchIngestModule extends IngestModuleAdapter implements FileIngestModule {
private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName()); private static final Logger logger = Logger.getLogger(FileExtMismatchIngestModule.class.getName());
private static int messageId = 0; // RJCTODO: This is not thread safe private final IngestServices services = IngestServices.getInstance();
private final IngestServices services = IngestServices.getDefault();
private final FileExtMismatchDetectorModuleSettings settings; private final FileExtMismatchDetectorModuleSettings settings;
private HashMap<String, String[]> SigTypeToExtMap = new HashMap<>(); private HashMap<String, String[]> SigTypeToExtMap = new HashMap<>();
private long processTime = 0; private long jobId;
private long numFiles = 0; private static AtomicLong processTime = new AtomicLong(0);
private static AtomicLong numFiles = new AtomicLong(0);
private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter();
FileExtMismatchIngestModule(FileExtMismatchDetectorModuleSettings settings) { FileExtMismatchIngestModule(FileExtMismatchDetectorModuleSettings settings) {
this.settings = settings; this.settings = settings;
@ -60,6 +62,8 @@ public class FileExtMismatchIngestModule extends IngestModuleAdapter implements
@Override @Override
public void startUp(IngestJobContext context) throws IngestModuleException { public void startUp(IngestJobContext context) throws IngestModuleException {
jobId = context.getJobId();
refCounter.incrementAndGet(jobId);
FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault(); FileExtMismatchXML xmlLoader = FileExtMismatchXML.getDefault();
SigTypeToExtMap = xmlLoader.load(); SigTypeToExtMap = xmlLoader.load();
} }
@ -78,17 +82,13 @@ public class FileExtMismatchIngestModule extends IngestModuleAdapter implements
return ProcessResult.OK; return ProcessResult.OK;
} }
if (settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) {
return ProcessResult.OK;
}
try { try {
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
boolean mismatchDetected = compareSigTypeToExt(abstractFile); boolean mismatchDetected = compareSigTypeToExt(abstractFile);
processTime += (System.currentTimeMillis() - startTime); processTime.getAndAdd(System.currentTimeMillis() - startTime);
numFiles++; numFiles.getAndIncrement();
if (mismatchDetected) { if (mismatchDetected) {
// add artifact // add artifact
@ -154,19 +154,22 @@ public class FileExtMismatchIngestModule extends IngestModuleAdapter implements
@Override @Override
public void shutDown(boolean ingestJobCancelled) { public void shutDown(boolean ingestJobCancelled) {
StringBuilder detailsSb = new StringBuilder(); // We only need to post the summary msg from the last module per job
detailsSb.append("<table border='0' cellpadding='4' width='280'>"); if (refCounter.decrementAndGet(jobId) == 0) {
detailsSb.append("<tr><td>").append(FileExtMismatchDetectorModuleFactory.getModuleName()).append("</td></tr>"); StringBuilder detailsSb = new StringBuilder();
detailsSb.append("<tr><td>").append( detailsSb.append("<table border='0' cellpadding='4' width='280'>");
NbBundle.getMessage(this.getClass(), "FileExtMismatchIngestModule.complete.totalProcTime")) detailsSb.append("<tr><td>").append(FileExtMismatchDetectorModuleFactory.getModuleName()).append("</td></tr>");
.append("</td><td>").append(processTime).append("</td></tr>\n"); detailsSb.append("<tr><td>").append(
detailsSb.append("<tr><td>").append( NbBundle.getMessage(this.getClass(), "FileExtMismatchIngestModule.complete.totalProcTime"))
NbBundle.getMessage(this.getClass(), "FileExtMismatchIngestModule.complete.totalFiles")) .append("</td><td>").append(processTime.get()).append("</td></tr>\n");
.append("</td><td>").append(numFiles).append("</td></tr>\n"); detailsSb.append("<tr><td>").append(
detailsSb.append("</table>"); NbBundle.getMessage(this.getClass(), "FileExtMismatchIngestModule.complete.totalFiles"))
services.postMessage(IngestMessage.createMessage(++messageId, IngestMessage.MessageType.INFO, FileExtMismatchDetectorModuleFactory.getModuleName(), .append("</td><td>").append(numFiles.get()).append("</td></tr>\n");
NbBundle.getMessage(this.getClass(), detailsSb.append("</table>");
"FileExtMismatchIngestModule.complete.svcMsg.text"), services.postMessage(IngestMessage.createMessage(IngestMessage.MessageType.INFO, FileExtMismatchDetectorModuleFactory.getModuleName(),
detailsSb.toString())); NbBundle.getMessage(this.getClass(),
"FileExtMismatchIngestModule.complete.svcMsg.text"),
detailsSb.toString()));
}
} }
} }

View File

@ -21,7 +21,6 @@
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Component id="skipTextPlain" min="-2" max="-2" attributes="0"/> <Component id="skipTextPlain" min="-2" max="-2" attributes="0"/>
<Component id="skipNoExtCheckBox" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="skipNoExtCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="skipKnownFilesCheckbox" alignment="0" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="0" pref="138" max="32767" attributes="0"/> <EmptySpace min="0" pref="138" max="32767" attributes="0"/>
</Group> </Group>
@ -33,9 +32,7 @@
<Component id="skipNoExtCheckBox" min="-2" max="-2" attributes="0"/> <Component id="skipNoExtCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="skipTextPlain" min="-2" max="-2" attributes="0"/> <Component id="skipTextPlain" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace pref="51" max="32767" attributes="0"/>
<Component id="skipKnownFilesCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="28" max="32767" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -45,7 +42,7 @@
<Properties> <Properties>
<Property name="selected" type="boolean" value="true"/> <Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -55,7 +52,7 @@
<Component class="javax.swing.JCheckBox" name="skipTextPlain"> <Component class="javax.swing.JCheckBox" name="skipTextPlain">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchModuleSettingsPanel.skipTextPlain.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchModuleSettingsPanel.skipTextPlain.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -65,15 +62,5 @@
<AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="skipTextPlain.setSelected(true);"/> <AuxValue name="JavaCodeGenerator_InitCodePost" type="java.lang.String" value="skipTextPlain.setSelected(true);"/>
</AuxValues> </AuxValues>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="skipKnownFilesCheckbox">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchModuleSettingsPanel.skipKnownFilesCheckbox.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="skipKnownFilesCheckboxActionPerformed"/>
</Events>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettingsPanel;
@ -38,7 +38,6 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
private void customizeComponents() { private void customizeComponents() {
skipNoExtCheckBox.setSelected(settings.skipFilesWithNoExtension()); skipNoExtCheckBox.setSelected(settings.skipFilesWithNoExtension());
skipTextPlain.setSelected(settings.skipFilesWithTextPlainMimeType()); skipTextPlain.setSelected(settings.skipFilesWithTextPlainMimeType());
skipKnownFilesCheckbox.setSelected(settings.skipKnownFiles());
} }
@Override @Override
@ -57,7 +56,6 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
skipNoExtCheckBox = new javax.swing.JCheckBox(); skipNoExtCheckBox = new javax.swing.JCheckBox();
skipTextPlain = new javax.swing.JCheckBox(); skipTextPlain = new javax.swing.JCheckBox();
skipKnownFilesCheckbox = new javax.swing.JCheckBox();
skipNoExtCheckBox.setSelected(true); skipNoExtCheckBox.setSelected(true);
skipNoExtCheckBox.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text")); // NOI18N skipNoExtCheckBox.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipNoExtCheckBox.text")); // NOI18N
@ -75,13 +73,6 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
} }
}); });
skipKnownFilesCheckbox.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchModuleSettingsPanel.class, "FileExtMismatchModuleSettingsPanel.skipKnownFilesCheckbox.text")); // NOI18N
skipKnownFilesCheckbox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
skipKnownFilesCheckboxActionPerformed(evt);
}
});
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
@ -90,8 +81,7 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
.addContainerGap() .addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(skipTextPlain) .addComponent(skipTextPlain)
.addComponent(skipNoExtCheckBox) .addComponent(skipNoExtCheckBox))
.addComponent(skipKnownFilesCheckbox))
.addGap(0, 138, Short.MAX_VALUE)) .addGap(0, 138, Short.MAX_VALUE))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
@ -100,9 +90,7 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
.addComponent(skipNoExtCheckBox) .addComponent(skipNoExtCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(skipTextPlain) .addComponent(skipTextPlain)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addContainerGap(51, Short.MAX_VALUE))
.addComponent(skipKnownFilesCheckbox)
.addContainerGap(28, Short.MAX_VALUE))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -114,12 +102,7 @@ final class FileExtMismatchModuleSettingsPanel extends IngestModuleIngestJobSett
settings.setSkipFilesWithTextPlainMimeType(skipTextPlain.isSelected()); settings.setSkipFilesWithTextPlainMimeType(skipTextPlain.isSelected());
}//GEN-LAST:event_skipTextPlainActionPerformed }//GEN-LAST:event_skipTextPlainActionPerformed
private void skipKnownFilesCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipKnownFilesCheckboxActionPerformed
settings.setSkipKnownFiles(skipKnownFilesCheckbox.isSelected());
}//GEN-LAST:event_skipKnownFilesCheckboxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox skipKnownFilesCheckbox;
private javax.swing.JCheckBox skipNoExtCheckBox; private javax.swing.JCheckBox skipNoExtCheckBox;
private javax.swing.JCheckBox skipTextPlain; private javax.swing.JCheckBox skipTextPlain;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables

View File

@ -2,7 +2,7 @@
* To change this template, choose Tools | Templates * To change this template, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport; import java.beans.PropertyChangeSupport;
@ -17,7 +17,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
@OptionsPanelController.TopLevelRegistration( @OptionsPanelController.TopLevelRegistration(
categoryName = "#OptionsCategory_Name_FileExtMismatchOptions", categoryName = "#OptionsCategory_Name_FileExtMismatchOptions",
iconBase = "org/sleuthkit/autopsy/fileextmismatch/options-icon.png", iconBase = "org/sleuthkit/autopsy/modules/fileextmismatch/options-icon.png",
position = 4, position = 4,
keywords = "#OptionsCategory_FileExtMismatch", keywords = "#OptionsCategory_FileExtMismatch",
keywordsCategory = "KeywordSearchOptions") keywordsCategory = "KeywordSearchOptions")

View File

@ -50,10 +50,10 @@
<Component class="javax.swing.JButton" name="saveButton"> <Component class="javax.swing.JButton" name="saveButton">
<Properties> <Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
<Image iconType="3" name="/org/sleuthkit/autopsy/fileextmismatch/save16.png"/> <Image iconType="3" name="/org/sleuthkit/autopsy/modules/fileextmismatch/save16.png"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.saveButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.saveButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/> <Property name="enabled" type="boolean" value="false"/>
</Properties> </Properties>
@ -128,7 +128,7 @@
<Component class="javax.swing.JLabel" name="jLabel1"> <Component class="javax.swing.JLabel" name="jLabel1">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.jLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -148,7 +148,7 @@
<Component class="javax.swing.JTextField" name="userTypeTextField"> <Component class="javax.swing.JTextField" name="userTypeTextField">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.userTypeTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.userTypeTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -158,7 +158,7 @@
<Component class="javax.swing.JButton" name="addTypeButton"> <Component class="javax.swing.JButton" name="addTypeButton">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.addTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.addTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -168,7 +168,7 @@
<Component class="javax.swing.JButton" name="removeTypeButton"> <Component class="javax.swing.JButton" name="removeTypeButton">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.removeTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.removeTypeButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -181,14 +181,14 @@
<Color blue="0" green="0" red="ff" type="rgb"/> <Color blue="0" green="0" red="ff" type="rgb"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.mimeErrLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.mimeErrLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="mimeRemoveErrLabel"> <Component class="javax.swing.JLabel" name="mimeRemoveErrLabel">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.mimeRemoveErrLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.mimeRemoveErrLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -254,7 +254,7 @@
<Component class="javax.swing.JTextField" name="userExtTextField"> <Component class="javax.swing.JTextField" name="userExtTextField">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.userExtTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.userExtTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -264,7 +264,7 @@
<Component class="javax.swing.JButton" name="addExtButton"> <Component class="javax.swing.JButton" name="addExtButton">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.addExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.addExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -287,7 +287,7 @@
<Component class="javax.swing.JButton" name="removeExtButton"> <Component class="javax.swing.JButton" name="removeExtButton">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.removeExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.removeExtButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events> <Events>
@ -297,7 +297,7 @@
<Component class="javax.swing.JLabel" name="extHeaderLabel"> <Component class="javax.swing.JLabel" name="extHeaderLabel">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.extHeaderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.extHeaderLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -307,14 +307,14 @@
<Color blue="0" green="0" red="ff" type="rgb"/> <Color blue="0" green="0" red="ff" type="rgb"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.extErrorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.extErrorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="extRemoveErrLabel"> <Component class="javax.swing.JLabel" name="extRemoveErrLabel">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.extRemoveErrLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.extRemoveErrLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>
@ -328,7 +328,7 @@
<Color blue="ff" green="0" red="0" type="rgb"/> <Color blue="ff" green="0" red="0" type="rgb"/>
</Property> </Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.saveMsgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties" key="FileExtMismatchSettingsPanel.saveMsgLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import java.awt.Color; import java.awt.Color;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,7 +32,7 @@ import javax.swing.table.AbstractTableModel;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSetttingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSetttingsPanel;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.filetypeid.FileTypeIdIngestModule; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeIdIngestModule;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
/** /**
@ -154,7 +154,7 @@ final class FileExtMismatchSettingsPanel extends IngestModuleGlobalSetttingsPane
extRemoveErrLabel = new javax.swing.JLabel(); extRemoveErrLabel = new javax.swing.JLabel();
saveMsgLabel = new javax.swing.JLabel(); saveMsgLabel = new javax.swing.JLabel();
saveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/fileextmismatch/save16.png"))); // NOI18N saveButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/fileextmismatch/save16.png"))); // NOI18N
saveButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.saveButton.text")); // NOI18N saveButton.setText(org.openide.util.NbBundle.getMessage(FileExtMismatchSettingsPanel.class, "FileExtMismatchSettingsPanel.saveButton.text")); // NOI18N
saveButton.setEnabled(false); saveButton.setEnabled(false);
saveButton.addActionListener(new java.awt.event.ActionListener() { saveButton.addActionListener(new java.awt.event.ActionListener() {

View File

@ -17,7 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.fileextmismatch; package org.sleuthkit.autopsy.modules.fileextmismatch;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -61,7 +61,7 @@ class FileExtMismatchXML {
this.filePath = filePath; this.filePath = filePath;
try { try {
boolean extracted = PlatformUtil.extractResourceToUserConfigDir(FileExtMismatchXML.class, DEFAULT_CONFIG_FILE_NAME); boolean extracted = PlatformUtil.extractResourceToUserConfigDir(FileExtMismatchXML.class, DEFAULT_CONFIG_FILE_NAME, false);
} catch (IOException ex) { } catch (IOException ex) {
logger.log(Level.SEVERE, "Error copying default mismatch configuration to user dir ", ex); logger.log(Level.SEVERE, "Error copying default mismatch configuration to user dir ", ex);
} }

Some files were not shown because too many files have changed in this diff Show More