Merged upstream/develop.

This commit is contained in:
Oliver Spohngellert 2016-06-22 08:58:01 -04:00
commit 4294885a63
203 changed files with 8355 additions and 5258 deletions

View File

@ -15,6 +15,22 @@
<specification-version>1.28.1</specification-version> <specification-version>1.28.1</specification-version>
</run-dependency> </run-dependency>
</dependency> </dependency>
<dependency>
<code-name-base>org.netbeans.api.progress.compat8</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.api.progress.nb</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
</run-dependency>
</dependency>
<dependency> <dependency>
<code-name-base>org.netbeans.core</code-name-base> <code-name-base>org.netbeans.core</code-name-base>
<build-prerequisite/> <build-prerequisite/>
@ -123,6 +139,22 @@
<specification-version>7.62.1</specification-version> <specification-version>7.62.1</specification-version>
</run-dependency> </run-dependency>
</dependency> </dependency>
<dependency>
<code-name-base>org.openide.filesystems.compat8</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.7.1</specification-version>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.openide.filesystems.nb</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.7.1</specification-version>
</run-dependency>
</dependency>
<dependency> <dependency>
<code-name-base>org.openide.modules</code-name-base> <code-name-base>org.openide.modules</code-name-base>
<build-prerequisite/> <build-prerequisite/>
@ -163,6 +195,14 @@
<specification-version>8.15.1</specification-version> <specification-version>8.15.1</specification-version>
</run-dependency> </run-dependency>
</dependency> </dependency>
<dependency>
<code-name-base>org.openide.util.ui</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.4.1</specification-version>
</run-dependency>
</dependency>
<dependency> <dependency>
<code-name-base>org.openide.windows</code-name-base> <code-name-base>org.openide.windows</code-name-base>
<build-prerequisite/> <build-prerequisite/>

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2015 Basis Technology Corp. * Copyright 2011-2016 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");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.actions; package org.sleuthkit.autopsy.actions;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -26,8 +27,8 @@ import org.openide.util.NbBundle;
import org.openide.util.Utilities; import org.openide.util.Utilities;
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.datamodel.TagName;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TagName;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
@ -38,7 +39,6 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
// This class is a singleton to support multi-selection of nodes, since // This class is a singleton to support multi-selection of nodes, since
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
// node in the array returns a reference to the same action object from Node.getActions(boolean). // node in the array returns a reference to the same action object from Node.getActions(boolean).
private static AddBlackboardArtifactTagAction instance; private static AddBlackboardArtifactTagAction instance;
public static synchronized AddBlackboardArtifactTagAction getInstance() { public static synchronized AddBlackboardArtifactTagAction getInstance() {
@ -63,7 +63,14 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
@Override @Override
protected void addTag(TagName tagName, String comment) { protected void addTag(TagName tagName, String comment) {
final Collection<? extends BlackboardArtifact> selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class); /*
* The documentation for Lookup.lookupAll() explicitly says that the
* collection it returns may contain duplicates. Within this invocation
* of addTag(), we don't want to tag the same BlackboardArtifact more
* than once, so we dedupe the BlackboardArtifacts by stuffing them into
* a HashSet.
*/
final Collection<BlackboardArtifact> selectedArtifacts = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
new Thread(() -> { new Thread(() -> {
for (BlackboardArtifact artifact : selectedArtifacts) { for (BlackboardArtifact artifact : selectedArtifacts) {

View File

@ -1,15 +1,15 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2015 Basis Technology Corp. * Copyright 2011-2016 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");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -19,13 +19,13 @@
package org.sleuthkit.autopsy.actions; package org.sleuthkit.autopsy.actions;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.Utilities; import org.openide.util.Utilities;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.TagsManager;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
@ -40,7 +40,6 @@ public class AddContentTagAction extends AddTagAction {
// This class is a singleton to support multi-selection of nodes, since // This class is a singleton to support multi-selection of nodes, since
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every // org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
// node in the array returns a reference to the same action object from Node.getActions(boolean). // node in the array returns a reference to the same action object from Node.getActions(boolean).
private static AddContentTagAction instance; private static AddContentTagAction instance;
public static synchronized AddContentTagAction getInstance() { public static synchronized AddContentTagAction getInstance() {
@ -63,7 +62,13 @@ public class AddContentTagAction extends AddTagAction {
@Override @Override
protected void addTag(TagName tagName, String comment) { protected void addTag(TagName tagName, String comment) {
final Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); /*
* The documentation for Lookup.lookupAll() explicitly says that the
* collection it returns may contain duplicates. Within this invocation
* of addTag(), we don't want to tag the same AbstractFile more than
* once, so we dedupe the AbstractFiles by stuffing them into a HashSet.
*/
final Collection<AbstractFile> selectedFiles = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
new Thread(() -> { new Thread(() -> {
for (AbstractFile file : selectedFiles) { for (AbstractFile file : selectedFiles) {

View File

@ -0,0 +1,51 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2016 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.util.logging.Level;
import org.openide.LifecycleManager;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
@ActionRegistration(displayName = "Exit", iconInMenu = true)
@ActionReference(path = "Menu/Case", position = 1000, separatorBefore = 999)
@ActionID(id = "org.sleuthkit.autopsy.casemodule.ExitAction", category = "Case")
final public class ExitAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
try {
Case currentCase = Case.getCurrentCase();
if (currentCase != null) {
currentCase.closeCase();
}
} catch (Exception ex) {
Logger.getLogger(ExitAction.class.getName()).log(Level.SEVERE, "Had a problem closing the case.", ex); //NON-NLS
} finally {
LifecycleManager.getDefault().exit();
}
}
}

View File

@ -39,7 +39,7 @@ import org.sleuthkit.autopsy.coreutils.Logger;
*/ */
@ActionRegistration( @ActionRegistration(
displayName = "#CTL_OpenOutputFolder", iconInMenu = true) displayName = "#CTL_OpenOutputFolder", iconInMenu = true)
@ActionReference(path = "Menu/Help", position = 1850) @ActionReference(path = "Menu/Tools", position = 1850, separatorBefore = 1849)
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help") @ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help")
public final class OpenOutputFolderAction extends CallableSystemAction { public final class OpenOutputFolderAction extends CallableSystemAction {

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...
Menu/File/OpenRecentCase=Open Recent Case Menu/Case/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:
@ -18,13 +18,8 @@ NewCaseVisualPanel1.caseDirTextField.text_1=
CasePropertiesForm.caseDirLabel.text=Case Directory: CasePropertiesForm.caseDirLabel.text=Case Directory:
CasePropertiesForm.crDateLabel.text=Created Date: CasePropertiesForm.crDateLabel.text=Created Date:
CasePropertiesForm.caseNameLabel.text=Case Name: CasePropertiesForm.caseNameLabel.text=Case Name:
CasePropertiesForm.crDateTextField.text=
CasePropertiesForm.caseNameTextField.text= CasePropertiesForm.caseNameTextField.text=
CasePropertiesForm.updateCaseNameButton.text=Update CasePropertiesForm.updateCaseNameButton.text=Update Name
CasePropertiesForm.casePropLabel.text=Case Information
CasePropertiesForm.genInfoLabel.text=General Information
CasePropertiesForm.imgInfoLabel.text=Images Information
CasePropertiesForm.OKButton.text=OK
CasePropertiesForm.deleteCaseButton.text=Delete Case CasePropertiesForm.deleteCaseButton.text=Delete Case
CueBannerPanel.autopsyLogo.text= CueBannerPanel.autopsyLogo.text=
CueBannerPanel.createNewLabel.text=Create New Case CueBannerPanel.createNewLabel.text=Create New Case
@ -38,8 +33,6 @@ OpenRecentCasePanel.cancelButton.text=Cancel
OpenRecentCasePanel.jLabel1.text=Recent Cases OpenRecentCasePanel.jLabel1.text=Recent Cases
CasePropertiesForm.caseNumberLabel.text=Case Number: CasePropertiesForm.caseNumberLabel.text=Case Number:
CasePropertiesForm.examinerLabel.text=Examiner: CasePropertiesForm.examinerLabel.text=Examiner:
CasePropertiesForm.caseNumberTextField.text=
CasePropertiesForm.examinerTextField.text=
NewCaseVisualPanel2.caseNumberTextField.text= NewCaseVisualPanel2.caseNumberTextField.text=
NewCaseVisualPanel2.examinerLabel.text=Examiner: NewCaseVisualPanel2.examinerLabel.text=Examiner:
NewCaseVisualPanel2.caseNumberLabel.text=Case Number: NewCaseVisualPanel2.caseNumberLabel.text=Case Number:
@ -231,9 +224,7 @@ NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user
NewCaseVisualPanel1.caseTypeLabel.text=Case Type: NewCaseVisualPanel1.caseTypeLabel.text=Case Type:
CasePropertiesForm.lbDbType.text=Case Type: CasePropertiesForm.lbDbType.text=Case Type:
CasePropertiesForm.tbDbType.text=
CasePropertiesForm.lbDbName.text=Database Name: CasePropertiesForm.lbDbName.text=Database Name:
CasePropertiesForm.tbDbName.text=
SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist! SingleUserCaseConverter.BadDatabaseFileName=Database file does not exist!
SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user! SingleUserCaseConverter.AlreadyMultiUser=Case is already multi-user!
SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique. SingleUserCaseConverter.NonUniqueDatabaseName=Database name not unique.
@ -245,3 +236,10 @@ CasePropertiesForm.imagesTable.columnModel.title1=Remove
CasePropertiesForm.imagesTable.columnModel.title0=Path CasePropertiesForm.imagesTable.columnModel.title0=Path
LocalFilesPanel.jButton1.text=Change LocalFilesPanel.jButton1.text=Change
LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default LocalFilesPanel.displayNameLabel.text=Logical File Set Display Name: Default
CaseInformationPanel.jPanel1.TabConstraints.tabTitle=tab1
CasePropertiesForm.caseNumberField.text=
CasePropertiesForm.examinerField.text=
CasePropertiesForm.crDateField.text=
CasePropertiesForm.caseDirField.text=
CasePropertiesForm.caseTypeField.text=
CasePropertiesForm.dbNameField.text=

View File

@ -4,7 +4,7 @@ CTL_CaseCloseAct=\u30b1\u30fc\u30b9\u3092\u9589\u3058\u308b
CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9... CTL_CaseNewAction=\u65b0\u898f\u30b1\u30fc\u30b9...
CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3... CTL_CasePropertiesAction=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3...
CTL_OpenAction=\u30b1\u30fc\u30b9\u3092\u958b\u304f... CTL_OpenAction=\u30b1\u30fc\u30b9\u3092\u958b\u304f...
Menu/File/OpenRecentCase=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f Menu/Case/OpenRecentCase=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\u524a\u9664 CTL_CaseDeleteAction=\u30b1\u30fc\u30b9\u3092\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
@ -16,10 +16,6 @@ CasePropertiesForm.caseDirLabel.text=\u30b1\u30fc\u30b9\u30c7\u30a3\u30ec\u30af\
CasePropertiesForm.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a CasePropertiesForm.crDateLabel.text=\u4f5c\u6210\u65e5\uff1a
CasePropertiesForm.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a CasePropertiesForm.caseNameLabel.text=\u30b1\u30fc\u30b9\u540d\uff1a
CasePropertiesForm.updateCaseNameButton.text=\u66f4\u65b0 CasePropertiesForm.updateCaseNameButton.text=\u66f4\u65b0
CasePropertiesForm.casePropLabel.text=\u30b1\u30fc\u30b9\u60c5\u5831
CasePropertiesForm.genInfoLabel.text=\u4e00\u822c\u60c5\u5831
CasePropertiesForm.imgInfoLabel.text=\u30a4\u30e1\u30fc\u30b8\u60c5\u5831
CasePropertiesForm.OKButton.text=OK
CasePropertiesForm.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664 CasePropertiesForm.deleteCaseButton.text=\u30b1\u30fc\u30b9\u3092\u524a\u9664
CueBannerPanel.createNewLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5c\u6210 CueBannerPanel.createNewLabel.text=\u65b0\u898f\u30b1\u30fc\u30b9\u3092\u4f5c\u6210
CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.openLabel.text=\u65e2\u5b58\u30b1\u30fc\u30b9\u3092\u958b\u304f

View File

@ -75,7 +75,7 @@ import org.sleuthkit.autopsy.events.AutopsyEventException;
import org.sleuthkit.autopsy.events.AutopsyEventPublisher; import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
import org.sleuthkit.autopsy.ingest.IngestJob; import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.RunIngestAction; import org.sleuthkit.autopsy.timeline.OpenTimelineAction;
import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.ContentTag;
@ -1519,27 +1519,20 @@ public class Case implements SleuthkitCase.ErrorObserver {
if (RuntimeProperties.coreComponentsAreActive()) { if (RuntimeProperties.coreComponentsAreActive()) {
// enable these menus // enable these menus
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
CallableSystemAction.get(RunIngestAction.class).setEnabled(true);
if (toChangeTo.hasData()) {
// open all top components
SwingUtilities.invokeLater(() -> {
CoreComponentControl.openCoreWindows();
});
} else {
// close all top components
SwingUtilities.invokeLater(() -> {
CoreComponentControl.closeCoreWindows();
});
}
}
if (RuntimeProperties.coreComponentsAreActive()) {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
CallableSystemAction.get(AddImageAction.class).setEnabled(true);
CallableSystemAction.get(CaseCloseAction.class).setEnabled(true);
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(true);
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(true); // Delete Case menu
CallableSystemAction.get(OpenTimelineAction.class).setEnabled(true);
if (toChangeTo.hasData()) {
// open all top components
CoreComponentControl.openCoreWindows();
} else {
// close all top components
CoreComponentControl.closeCoreWindows();
}
updateMainWindowTitle(currentCase.getName()); updateMainWindowTitle(currentCase.getName());
}); });
} else { } else {
@ -1550,9 +1543,9 @@ public class Case implements SleuthkitCase.ErrorObserver {
} }
} else { // case is closed } else { // case is closed
if (RuntimeProperties.coreComponentsAreActive()) { SwingUtilities.invokeLater(() -> {
if (RuntimeProperties.coreComponentsAreActive()) {
SwingUtilities.invokeLater(() -> {
// close all top components first // close all top components first
CoreComponentControl.closeCoreWindows(); CoreComponentControl.closeCoreWindows();
@ -1561,16 +1554,11 @@ public class Case implements SleuthkitCase.ErrorObserver {
CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu CallableSystemAction.get(CaseCloseAction.class).setEnabled(false); // Case Close menu
CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu CallableSystemAction.get(CasePropertiesAction.class).setEnabled(false); // Case Properties menu
CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu CallableSystemAction.get(CaseDeleteAction.class).setEnabled(false); // Delete Case menu
CallableSystemAction.get(RunIngestAction.class).setEnabled(false); CallableSystemAction.get(OpenTimelineAction.class).setEnabled(false);
}); }
}
//clear pending notifications //clear pending notifications
SwingUtilities.invokeLater(() -> {
MessageNotifyUtil.Notify.clear(); MessageNotifyUtil.Notify.clear();
});
SwingUtilities.invokeLater(() -> {
Frame f = WindowManager.getDefault().getMainWindow(); Frame f = WindowManager.getDefault().getMainWindow();
f.setTitle(Case.getAppName()); // set the window name to just application name f.setTitle(Case.getAppName()); // set the window name to just application name
}); });
@ -1666,7 +1654,7 @@ public class Case implements SleuthkitCase.ErrorObserver {
* Deletes reports from the case. * Deletes reports from the case.
* *
* @param reports Collection of Report to be deleted from the case. * @param reports Collection of Report to be deleted from the case.
* @param deleteFromDisk No longer supported - ignored. * @param deleteFromDisk No longer supported - ignored.
* *
* @throws TskCoreException * @throws TskCoreException
* @deprecated Use deleteReports(Collection<? extends Report> reports) * @deprecated Use deleteReports(Collection<? extends Report> reports)
@ -1676,5 +1664,5 @@ public class Case implements SleuthkitCase.ErrorObserver {
public void deleteReports(Collection<? extends Report> reports, boolean deleteFromDisk) throws TskCoreException { public void deleteReports(Collection<? extends Report> reports, boolean deleteFromDisk) throws TskCoreException {
deleteReports(reports); deleteReports(reports);
} }
} }

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
<Component id="jPanel1" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JPanel" name="jPanel1">
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="tabbedPane" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<Component id="tabbedPane" pref="228" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JTabbedPane" name="tabbedPane">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[420, 200]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,90 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.casemodule;
import java.util.Map;
import org.openide.util.NbBundle.Messages;
/**
*
* @author oliver
*/
public class CaseInformationPanel extends javax.swing.JPanel {
/**
* Creates new form CaseInformationPanel
*/
public CaseInformationPanel() {
initComponents();
customizeComponents();
}
@Messages({"CaseInformationPanel.caseDetails.header=Case Details"})
private void customizeComponents() {
try {
Case currentCase = Case.getCurrentCase();
String crDate = currentCase.getCreatedDate();
String caseDir = currentCase.getCaseDirectory();
// put the image paths information into hashmap
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths);
cpf.setSize(cpf.getPreferredSize());
this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf);
} catch (CaseMetadata.CaseMetadataException ex) {
//TOLOG
}
}
/**
* 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() {
jPanel1 = new javax.swing.JPanel();
tabbedPane = new javax.swing.JTabbedPane();
tabbedPane.setPreferredSize(new java.awt.Dimension(420, 200));
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addComponent(tabbedPane, javax.swing.GroupLayout.DEFAULT_SIZE, 228, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel jPanel1;
private javax.swing.JTabbedPane tabbedPane;
// End of variables declaration//GEN-END:variables
}

View File

@ -20,9 +20,6 @@ package org.sleuthkit.autopsy.casemodule;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JDialog; import javax.swing.JDialog;
@ -61,32 +58,16 @@ final class CasePropertiesAction extends CallableSystemAction {
// create the popUp window for it // create the popUp window for it
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title"); String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
final JFrame frame = new JFrame(title); final JFrame frame = new JFrame(title);
popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal popUpWindow = new JDialog(frame, title, false); // to make the popUp Window to be modal
// get the information that needed
Case currentCase = Case.getCurrentCase();
String crDate = currentCase.getCreatedDate();
String caseDir = currentCase.getCaseDirectory();
// put the image paths information into hashmap
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
// create the case properties form // create the case properties form
CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths); CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
// add the command to close the window to the button on the Case Properties form / panel
cpf.setOKButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
popUpWindow.dispose();
}
});
// add the case properties form / panel to the popup window // add the case properties form / panel to the popup window
popUpWindow.add(cpf); popUpWindow.add(caseInformationPanel);
popUpWindow.setResizable(true);
popUpWindow.pack(); popUpWindow.pack();
popUpWindow.setResizable(false);
// set the location of the popUp Window on the center of the screen // set the location of the popUp Window on the center of the screen
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();

View File

@ -33,437 +33,307 @@
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0"> <Component id="jPanel1" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="casePropLabel" pref="440" max="32767" attributes="0"/>
<Component id="imagesTableScrollPane" alignment="0" pref="440" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="caseNameLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="caseNumberLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="examinerLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="caseDirLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="crDateLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="lbDbType" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="caseNameTextField" alignment="0" pref="245" max="32767" attributes="1"/>
<Component id="caseNumberTextField" alignment="0" pref="245" max="32767" attributes="1"/>
<Component id="examinerTextField" alignment="0" pref="245" max="32767" attributes="1"/>
<Component id="crDateTextField" alignment="0" max="32767" attributes="1"/>
<Component id="jScrollPane2" alignment="0" max="32767" attributes="0"/>
<Component id="tbDbType" alignment="0" max="32767" attributes="0"/>
<Component id="tbDbName" alignment="0" max="32767" attributes="0"/>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="deleteCaseButton" max="32767" attributes="1"/>
<Component id="updateCaseNameButton" max="32767" attributes="1"/>
</Group>
</Group>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="genInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="imgInfoLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="181" max="-2" attributes="0"/>
<Component id="OKButton" min="-2" pref="78" max="-2" attributes="0"/>
</Group>
<Component id="lbDbName" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group> </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="0" attributes="0"> <Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="casePropLabel" min="-2" pref="33" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="genInfoLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseNameLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="caseNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="updateCaseNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseNumberLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="caseNumberTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="examinerLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="examinerTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="crDateLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="crDateTextField" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" min="-2" pref="40" max="-2" attributes="0"/>
<Component id="caseDirLabel" min="-2" pref="14" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="tbDbType" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="lbDbType" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lbDbName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="tbDbName" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="imgInfoLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="9" max="-2" attributes="0"/>
<Component id="deleteCaseButton" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="imagesTableScrollPane" min="-2" pref="170" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="OKButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Component class="javax.swing.JLabel" name="casePropLabel"> <Container class="javax.swing.JPanel" name="jPanel1">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="casePropLabel" property="font" relativeSize="false" size="24"/>
</FontInfo>
</Property>
<Property name="horizontalAlignment" type="int" value="0"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.casePropLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseNameLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseNameLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="crDateLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="crDateLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseDirLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseDirLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="crDateTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="crDateTextField" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseNameTextField">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseNameTextField" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="updateCaseNameButton">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="updateCaseNameButton" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.updateCaseNameButton.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="updateCaseNameButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="genInfoLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="genInfoLabel" property="font" relativeSize="false" size="14"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.genInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="imgInfoLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="true" component="imgInfoLabel" property="font" relativeSize="false" size="14"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.imgInfoLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JButton" name="OKButton">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="OKButton" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.OKButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Container class="javax.swing.JScrollPane" name="imagesTableScrollPane">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="imagesTableScrollPane" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
</Properties>
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/> <Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="lbDbName" min="-2" max="-2" attributes="0"/>
<Component id="lbDbType" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="caseDirLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="caseDirField" max="32767" attributes="0"/>
<Component id="caseTypeField" max="32767" attributes="0"/>
<Component id="dbNameField" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="0" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="crDateLabel" min="-2" max="-2" attributes="0"/>
<Component id="examinerLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="caseNumberLabel" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="separate" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="examinerField" max="32767" attributes="0"/>
<Component id="caseNumberField" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="caseNameTextField" pref="243" max="32767" attributes="1"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="updateCaseNameButton" min="-2" pref="104" max="-2" attributes="1"/>
</Group>
<Component id="crDateField" alignment="0" max="32767" attributes="0"/>
</Group>
</Group>
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
<Component id="deleteCaseButton" min="-2" pref="106" max="-2" attributes="1"/>
</Group>
</Group>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="caseNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="392" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="1" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="updateCaseNameButton" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="32767" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" attributes="0">
<Component id="caseNumberField" min="-2" pref="14" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="examinerField" min="-2" pref="14" max="-2" attributes="0"/>
<Component id="examinerLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="crDateField" alignment="1" min="-2" pref="14" max="-2" attributes="0"/>
<Component id="crDateLabel" alignment="1" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" max="-2" attributes="0">
<Component id="caseDirLabel" max="32767" attributes="0"/>
<Component id="caseDirField" max="32767" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="caseTypeField" alignment="0" min="-2" pref="14" max="-2" attributes="0"/>
<Component id="lbDbType" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="lbDbName" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="dbNameField" alignment="3" min="-2" pref="14" max="-2" attributes="0"/>
</Group>
</Group>
<Component id="caseNumberLabel" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Component id="deleteCaseButton" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
<Group type="103" rootIndex="1" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="caseNameLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace pref="173" max="32767" attributes="0"/>
</Group>
</Group>
</Group>
</DimensionLayout>
</Layout>
<SubComponents> <SubComponents>
<Component class="javax.swing.JTable" name="imagesTable"> <Component class="javax.swing.JLabel" name="caseNameLabel">
<Properties> <Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor"> <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true"> <FontInfo relative="true">
<Font bold="false" component="imagesTable" property="font" relativeSize="false" size="11"/> <Font bold="false" component="caseNameLabel" property="font" relativeSize="false" size="11"/>
</FontInfo> </FontInfo>
</Property> </Property>
<Property name="model" type="javax.swing.table.TableModel" editor="org.netbeans.modules.form.editors2.TableModelEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<Table columnCount="2" rowCount="0"> <ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Column editable="false" title="Path" type="java.lang.Object"/>
<Column editable="true" title="Remove" type="java.lang.Object"/>
</Table>
</Property> </Property>
<Property name="columnModel" type="javax.swing.table.TableColumnModel" editor="org.netbeans.modules.form.editors2.TableColumnModelEditor">
<TableColumnModel selectionModel="0">
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
<Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.imagesTable.path" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Title>
<Editor/>
<Renderer/>
</Column>
<Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true">
<Title editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.imagesTable.remove" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Title>
<Editor/>
<Renderer/>
</Column>
</TableColumnModel>
</Property>
<Property name="showHorizontalLines" type="boolean" value="false"/>
<Property name="showVerticalLines" type="boolean" value="false"/>
<Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor">
<TableHeader reorderingAllowed="false" resizingAllowed="true"/>
</Property>
<Property name="updateSelectionOnSort" type="boolean" value="false"/>
</Properties> </Properties>
</Component> </Component>
</SubComponents> <Component class="javax.swing.JLabel" name="crDateLabel">
</Container>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="jScrollPane2" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
</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="caseDirTextArea">
<Properties> <Properties>
<Property name="editable" type="boolean" value="false"/> <Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<Property name="background" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor"> <FontInfo relative="true">
<Color blue="f0" green="f0" red="f0" type="rgb"/> <Font bold="false" component="crDateLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseDirLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseDirLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseDirLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseNameTextField">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseNameTextField" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNameTextField.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="caseNameTextFieldActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="updateCaseNameButton">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="updateCaseNameButton" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.updateCaseNameButton.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="updateCaseNameButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JButton" name="deleteCaseButton">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="deleteCaseButton" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.deleteCaseButton.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="deleteCaseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="caseNumberLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseNumberLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="examinerLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="examinerLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.examinerLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lbDbType">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="lbDbType" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.lbDbType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lbDbName">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="lbDbName" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.lbDbName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseNumberField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNumberField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="examinerField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.examinerField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="crDateField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.crDateField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseDirField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseDirField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[25, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="dbNameField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.dbNameField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[25, 14]"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="caseTypeField">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseTypeField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[1, 0]"/>
</Property> </Property>
<Property name="columns" type="int" value="20"/>
<Property name="rows" type="int" value="1"/>
<Property name="requestFocusEnabled" type="boolean" value="false"/>
</Properties> </Properties>
</Component> </Component>
</SubComponents> </SubComponents>
</Container> </Container>
<Component class="javax.swing.JButton" name="deleteCaseButton">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="deleteCaseButton" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.deleteCaseButton.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="deleteCaseButtonActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="caseNumberLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseNumberLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNumberLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="examinerLabel">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="examinerLabel" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.examinerLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="caseNumberTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="caseNumberTextField" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.caseNumberTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="examinerTextField">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="examinerTextField" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.examinerTextField.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lbDbType">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="lbDbType" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.lbDbType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="tbDbType">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="tbDbType" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.tbDbType.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="lbDbName">
<Properties>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="lbDbName" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.lbDbName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JTextField" name="tbDbName">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="font" type="java.awt.Font" editor="org.netbeans.modules.form.editors2.FontEditor">
<FontInfo relative="true">
<Font bold="false" component="tbDbName" property="font" relativeSize="false" size="11"/>
</FontInfo>
</Property>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CasePropertiesForm.tbDbName.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -17,36 +17,33 @@
* limitations under the License. * limitations under the License.
*/ */
/* /*
* CasePropertiesForm.java * CasePropertiesForm.java
* *
* Created on Mar 14, 2011, 1:48:20 PM * Created on Mar 14, 2011, 1:48:20 PM
*/ */
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.nio.file.Paths;
import java.awt.event.ActionListener;
import java.io.File; import java.io.File;
import java.util.Map; import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane; import javax.swing.JOptionPane;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.swing.table.DefaultTableModel;
import org.openide.DialogDescriptor; import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer; import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger;
/** /**
* The form where user can change / update the properties of the current case * The form where user can change / update the properties of the current case
* metadata. * metadata.
*/ */
class CasePropertiesForm extends javax.swing.JPanel { class CasePropertiesForm extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Case current = null; private Case current = null;
private static JPanel caller; // panel for error private static JPanel caller; // panel for error
@ -55,15 +52,15 @@ class CasePropertiesForm extends javax.swing.JPanel {
private String shrinkPath(String path, int targetLength) { private String shrinkPath(String path, int targetLength) {
if (path.length() > targetLength) { if (path.length() > targetLength) {
String fill = "..."; String fill = "...";
int partsLength = targetLength - fill.length(); int partsLength = targetLength - fill.length();
String front = path.substring(0, partsLength / 4); String front = path.substring(0, partsLength / 4);
int frontSep = front.lastIndexOf(File.separatorChar); int frontSep = front.lastIndexOf(File.separatorChar);
if (frontSep != -1) { if (frontSep != -1) {
front = front.substring(0, frontSep + 1); front = front.substring(0, frontSep + 1);
} }
String back = path.substring(partsLength * 3 / 4); String back = path.substring(partsLength * 3 / 4);
int backSep = back.indexOf(File.separatorChar); int backSep = back.indexOf(File.separatorChar);
if (backSep != -1) { if (backSep != -1) {
@ -81,52 +78,35 @@ class CasePropertiesForm extends javax.swing.JPanel {
CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException { CasePropertiesForm(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException {
initComponents(); initComponents();
caseNameTextField.setText(currentCase.getName()); caseNameTextField.setText(currentCase.getName());
caseNumberTextField.setText(currentCase.getNumber()); String caseNumber = currentCase.getNumber();
examinerTextField.setText(currentCase.getExaminer()); if (!caseNumber.equals("")) {
crDateTextField.setText(crDate); caseNumberField.setText(caseNumber);
caseDirTextArea.setText(caseDir); } else {
caseNumberField.setText("N/A");
}
String examiner = currentCase.getExaminer();
if (!examiner.equals("")) {
examinerField.setText(examiner);
} else {
examinerField.setText("N/A");
}
crDateField.setText(crDate);
caseDirField.setText(caseDir);
current = currentCase; current = currentCase;
CaseMetadata caseMetadata = currentCase.getCaseMetadata(); CaseMetadata caseMetadata = currentCase.getCaseMetadata();
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) { if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
tbDbName.setText(caseMetadata.getCaseDatabasePath()); dbNameField.setText(caseMetadata.getCaseDatabasePath());
} else { } else {
tbDbName.setText(caseMetadata.getCaseDatabaseName()); dbNameField.setText(caseMetadata.getCaseDatabaseName());
} }
Case.CaseType caseType = caseMetadata.getCaseType(); Case.CaseType caseType = caseMetadata.getCaseType();
tbDbType.setText(caseType.getLocalizedDisplayName()); caseTypeField.setText(caseType.getLocalizedDisplayName());
if (caseType == Case.CaseType.SINGLE_USER_CASE) { if (caseType == Case.CaseType.SINGLE_USER_CASE) {
deleteCaseButton.setEnabled(true); deleteCaseButton.setEnabled(true);
} else { } else {
deleteCaseButton.setEnabled(false); deleteCaseButton.setEnabled(false);
} }
int totalImages = imgPaths.size();
// create the headers and add all the rows
// Header names are internationalized via the generated code, do not overwrite.
String[] headers = {imagesTable.getColumnName(0),
imagesTable.getColumnName(1)};
String[][] rows = new String[totalImages][];
int i = 0;
for (long key : imgPaths.keySet()) {
String path = imgPaths.get(key);
String shortenPath = shrinkPath(path, 70);
rows[i] = new String[]{shortenPath};
i++;
}
// create the table inside with the imgPaths information
DefaultTableModel model = new DefaultTableModel(rows, headers) {
@Override
// make the cells in the FileContentTable "read only"
public boolean isCellEditable(int row, int column) {
return false;
//return column == lastColumn; // make the last column (Remove button), only the editable
}
};
imagesTable.setModel(model);
} }
/** /**
@ -149,38 +129,28 @@ class CasePropertiesForm extends javax.swing.JPanel {
jScrollPane1 = new javax.swing.JScrollPane(); jScrollPane1 = new javax.swing.JScrollPane();
jTextArea1 = new javax.swing.JTextArea(); jTextArea1 = new javax.swing.JTextArea();
casePropLabel = new javax.swing.JLabel(); jPanel1 = new javax.swing.JPanel();
caseNameLabel = new javax.swing.JLabel(); caseNameLabel = new javax.swing.JLabel();
crDateLabel = new javax.swing.JLabel(); crDateLabel = new javax.swing.JLabel();
caseDirLabel = new javax.swing.JLabel(); caseDirLabel = new javax.swing.JLabel();
crDateTextField = new javax.swing.JTextField();
caseNameTextField = new javax.swing.JTextField(); caseNameTextField = new javax.swing.JTextField();
updateCaseNameButton = new javax.swing.JButton(); updateCaseNameButton = new javax.swing.JButton();
genInfoLabel = new javax.swing.JLabel();
imgInfoLabel = new javax.swing.JLabel();
OKButton = new javax.swing.JButton();
imagesTableScrollPane = new javax.swing.JScrollPane();
imagesTable = new javax.swing.JTable();
jScrollPane2 = new javax.swing.JScrollPane();
caseDirTextArea = new javax.swing.JTextArea();
deleteCaseButton = new javax.swing.JButton(); deleteCaseButton = new javax.swing.JButton();
caseNumberLabel = new javax.swing.JLabel(); caseNumberLabel = new javax.swing.JLabel();
examinerLabel = new javax.swing.JLabel(); examinerLabel = new javax.swing.JLabel();
caseNumberTextField = new javax.swing.JTextField();
examinerTextField = new javax.swing.JTextField();
lbDbType = new javax.swing.JLabel(); lbDbType = new javax.swing.JLabel();
tbDbType = new javax.swing.JTextField();
lbDbName = new javax.swing.JLabel(); lbDbName = new javax.swing.JLabel();
tbDbName = new javax.swing.JTextField(); caseNumberField = new javax.swing.JLabel();
examinerField = new javax.swing.JLabel();
crDateField = new javax.swing.JLabel();
caseDirField = new javax.swing.JLabel();
dbNameField = new javax.swing.JLabel();
caseTypeField = new javax.swing.JLabel();
jTextArea1.setColumns(20); jTextArea1.setColumns(20);
jTextArea1.setRows(5); jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1); jScrollPane1.setViewportView(jTextArea1);
casePropLabel.setFont(casePropLabel.getFont().deriveFont(casePropLabel.getFont().getStyle() | java.awt.Font.BOLD, 24));
casePropLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
casePropLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.casePropLabel.text")); // NOI18N
caseNameLabel.setFont(caseNameLabel.getFont().deriveFont(caseNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); caseNameLabel.setFont(caseNameLabel.getFont().deriveFont(caseNameLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameLabel.text")); // NOI18N caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameLabel.text")); // NOI18N
@ -190,12 +160,13 @@ class CasePropertiesForm extends javax.swing.JPanel {
caseDirLabel.setFont(caseDirLabel.getFont().deriveFont(caseDirLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); caseDirLabel.setFont(caseDirLabel.getFont().deriveFont(caseDirLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseDirLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirLabel.text")); // NOI18N caseDirLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirLabel.text")); // NOI18N
crDateTextField.setEditable(false);
crDateTextField.setFont(crDateTextField.getFont().deriveFont(crDateTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
crDateTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateTextField.text")); // NOI18N
caseNameTextField.setFont(caseNameTextField.getFont().deriveFont(caseNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); caseNameTextField.setFont(caseNameTextField.getFont().deriveFont(caseNameTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseNameTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameTextField.text")); // NOI18N caseNameTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNameTextField.text")); // NOI18N
caseNameTextField.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
caseNameTextFieldActionPerformed(evt);
}
});
updateCaseNameButton.setFont(updateCaseNameButton.getFont().deriveFont(updateCaseNameButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); updateCaseNameButton.setFont(updateCaseNameButton.getFont().deriveFont(updateCaseNameButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
updateCaseNameButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.updateCaseNameButton.text")); // NOI18N updateCaseNameButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.updateCaseNameButton.text")); // NOI18N
@ -205,53 +176,6 @@ class CasePropertiesForm extends javax.swing.JPanel {
} }
}); });
genInfoLabel.setFont(genInfoLabel.getFont().deriveFont(genInfoLabel.getFont().getStyle() | java.awt.Font.BOLD, 14));
genInfoLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.genInfoLabel.text")); // NOI18N
imgInfoLabel.setFont(imgInfoLabel.getFont().deriveFont(imgInfoLabel.getFont().getStyle() | java.awt.Font.BOLD, 14));
imgInfoLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imgInfoLabel.text")); // NOI18N
OKButton.setFont(OKButton.getFont().deriveFont(OKButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
OKButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.OKButton.text")); // NOI18N
imagesTableScrollPane.setFont(imagesTableScrollPane.getFont().deriveFont(imagesTableScrollPane.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
imagesTable.setFont(imagesTable.getFont().deriveFont(imagesTable.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
imagesTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
},
new String [] {
"Path", "Remove"
}
) {
boolean[] canEdit = new boolean [] {
false, true
};
public boolean isCellEditable(int rowIndex, int columnIndex) {
return canEdit [columnIndex];
}
});
imagesTable.setShowHorizontalLines(false);
imagesTable.setShowVerticalLines(false);
imagesTable.getTableHeader().setReorderingAllowed(false);
imagesTable.setUpdateSelectionOnSort(false);
imagesTableScrollPane.setViewportView(imagesTable);
if (imagesTable.getColumnModel().getColumnCount() > 0) {
imagesTable.getColumnModel().getColumn(0).setHeaderValue(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imagesTable.columnModel.title0")); // NOI18N
imagesTable.getColumnModel().getColumn(1).setHeaderValue(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.imagesTable.columnModel.title1")); // NOI18N
}
jScrollPane2.setFont(jScrollPane2.getFont().deriveFont(jScrollPane2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseDirTextArea.setEditable(false);
caseDirTextArea.setBackground(new java.awt.Color(240, 240, 240));
caseDirTextArea.setColumns(20);
caseDirTextArea.setRows(1);
caseDirTextArea.setRequestFocusEnabled(false);
jScrollPane2.setViewportView(caseDirTextArea);
deleteCaseButton.setFont(deleteCaseButton.getFont().deriveFont(deleteCaseButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); deleteCaseButton.setFont(deleteCaseButton.getFont().deriveFont(deleteCaseButton.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
deleteCaseButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.deleteCaseButton.text")); // NOI18N deleteCaseButton.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.deleteCaseButton.text")); // NOI18N
deleteCaseButton.addActionListener(new java.awt.event.ActionListener() { deleteCaseButton.addActionListener(new java.awt.event.ActionListener() {
@ -266,117 +190,119 @@ class CasePropertiesForm extends javax.swing.JPanel {
examinerLabel.setFont(examinerLabel.getFont().deriveFont(examinerLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); examinerLabel.setFont(examinerLabel.getFont().deriveFont(examinerLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
examinerLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerLabel.text")); // NOI18N examinerLabel.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerLabel.text")); // NOI18N
caseNumberTextField.setEditable(false);
caseNumberTextField.setFont(caseNumberTextField.getFont().deriveFont(caseNumberTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
caseNumberTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNumberTextField.text")); // NOI18N
examinerTextField.setEditable(false);
examinerTextField.setFont(examinerTextField.getFont().deriveFont(examinerTextField.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
examinerTextField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerTextField.text")); // NOI18N
lbDbType.setFont(lbDbType.getFont().deriveFont(lbDbType.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); lbDbType.setFont(lbDbType.getFont().deriveFont(lbDbType.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
lbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbType.text")); // NOI18N lbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbType.text")); // NOI18N
tbDbType.setEditable(false);
tbDbType.setFont(tbDbType.getFont().deriveFont(tbDbType.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
tbDbType.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.tbDbType.text")); // NOI18N
lbDbName.setFont(lbDbName.getFont().deriveFont(lbDbName.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); lbDbName.setFont(lbDbName.getFont().deriveFont(lbDbName.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
lbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbName.text")); // NOI18N lbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.lbDbName.text")); // NOI18N
tbDbName.setEditable(false); caseNumberField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseNumberField.text")); // NOI18N
tbDbName.setFont(tbDbName.getFont().deriveFont(tbDbName.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
tbDbName.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.tbDbName.text")); // NOI18N examinerField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.examinerField.text")); // NOI18N
crDateField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.crDateField.text")); // NOI18N
caseDirField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseDirField.text")); // NOI18N
caseDirField.setMinimumSize(new java.awt.Dimension(25, 14));
dbNameField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.dbNameField.text")); // NOI18N
dbNameField.setMinimumSize(new java.awt.Dimension(25, 14));
caseTypeField.setText(org.openide.util.NbBundle.getMessage(CasePropertiesForm.class, "CasePropertiesForm.caseTypeField.text")); // NOI18N
caseTypeField.setMaximumSize(new java.awt.Dimension(1, 0));
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbDbName)
.addComponent(lbDbType)
.addComponent(caseDirLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(caseDirField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(caseTypeField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(dbNameField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(crDateLabel)
.addComponent(examinerLabel)
.addComponent(caseNumberLabel))
.addGap(18, 18, 18)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(examinerField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(caseNumberField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(caseNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 243, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(updateCaseNameButton, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(crDateField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addGap(0, 0, Short.MAX_VALUE)
.addComponent(deleteCaseButton, javax.swing.GroupLayout.PREFERRED_SIZE, 106, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(caseNameLabel)
.addContainerGap(392, Short.MAX_VALUE)))
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(updateCaseNameButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(caseNumberField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(examinerField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(examinerLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(crDateField, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(crDateLabel, javax.swing.GroupLayout.Alignment.TRAILING))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(caseDirLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(caseDirField, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseTypeField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lbDbType))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lbDbName)
.addComponent(dbNameField, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addComponent(caseNumberLabel))
.addGap(10, 10, 10)
.addComponent(deleteCaseButton)
.addContainerGap())
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(caseNameLabel)
.addContainerGap(173, Short.MAX_VALUE)))
);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(casePropLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE)
.addComponent(imagesTableScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 440, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(caseNameLabel)
.addComponent(caseNumberLabel)
.addComponent(examinerLabel)
.addComponent(caseDirLabel)
.addComponent(crDateLabel)
.addComponent(lbDbType))
.addGap(18, 18, 18)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(caseNameTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
.addComponent(caseNumberTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
.addComponent(examinerTextField, javax.swing.GroupLayout.DEFAULT_SIZE, 245, Short.MAX_VALUE)
.addComponent(crDateTextField)
.addComponent(jScrollPane2)
.addComponent(tbDbType)
.addComponent(tbDbName))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(deleteCaseButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(updateCaseNameButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(genInfoLabel)
.addComponent(imgInfoLabel)
.addGroup(layout.createSequentialGroup()
.addGap(181, 181, 181)
.addComponent(OKButton, javax.swing.GroupLayout.PREFERRED_SIZE, 78, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(lbDbName))
.addGap(0, 0, Short.MAX_VALUE)))
.addContainerGap())
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()
.addComponent(casePropLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 33, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(genInfoLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseNameLabel)
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(updateCaseNameButton))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(caseNumberLabel)
.addComponent(caseNumberTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(examinerLabel)
.addComponent(examinerTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(crDateLabel)
.addComponent(crDateTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(caseDirLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 14, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(tbDbType, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lbDbType))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lbDbName)
.addComponent(tbDbName, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(18, 18, 18)
.addComponent(imgInfoLabel))
.addGroup(layout.createSequentialGroup()
.addGap(9, 9, 9)
.addComponent(deleteCaseButton)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(imagesTableScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 170, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(OKButton)
.addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
@ -399,38 +325,36 @@ class CasePropertiesForm extends javax.swing.JPanel {
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.empty.title"), "CasePropertiesForm.updateCaseName.msgDlg.empty.title"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} else // check if case Name contain one of this following symbol:
// \ / : * ? " < > |
if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":")
|| newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"")
|| newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) {
String errorMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg");
JOptionPane.showMessageDialog(caller, errorMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
JOptionPane.ERROR_MESSAGE);
} else { } else {
// check if case Name contain one of this following symbol: // ask for the confirmation first
// \ / : * ? " < > | String confMsg = NbBundle
if (newCaseName.contains("\\") || newCaseName.contains("/") || newCaseName.contains(":") .getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
|| newCaseName.contains("*") || newCaseName.contains("?") || newCaseName.contains("\"") newCaseName);
|| newCaseName.contains("<") || newCaseName.contains(">") || newCaseName.contains("|")) { NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
String errorMsg = NbBundle NbBundle.getMessage(this.getClass(),
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg"); "CasePropertiesForm.updateCaseName.confMsg.title"),
JOptionPane.showMessageDialog(caller, errorMsg, NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
NbBundle.getMessage(this.getClass(), d.setValue(NotifyDescriptor.NO_OPTION);
"CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title"),
JOptionPane.ERROR_MESSAGE); Object res = DialogDisplayer.getDefault().notify(d);
} else { if (res != null && res == DialogDescriptor.YES_OPTION) {
// ask for the confirmation first // if user select "Yes"
String confMsg = NbBundle String oldPath = current.getCaseMetadata().getFilePath().toString();
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName, try {
newCaseName); current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg, } catch (Exception ex) {
NbBundle.getMessage(this.getClass(), Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
"CasePropertiesForm.updateCaseName.confMsg.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d);
if (res != null && res == DialogDescriptor.YES_OPTION) {
// if user select "Yes"
String oldPath = current.getCaseMetadata().getFilePath().toString();
try {
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
} catch (Exception ex) {
Logger.getLogger(CasePropertiesForm.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
}
} }
} }
} }
@ -441,40 +365,30 @@ class CasePropertiesForm extends javax.swing.JPanel {
CallableSystemAction.get(CaseDeleteAction.class).actionPerformed(evt); CallableSystemAction.get(CaseDeleteAction.class).actionPerformed(evt);
}//GEN-LAST:event_deleteCaseButtonActionPerformed }//GEN-LAST:event_deleteCaseButtonActionPerformed
/** private void caseNameTextFieldActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseNameTextFieldActionPerformed
* Sets the listener for the OK button // TODO add your handling code here:
* }//GEN-LAST:event_caseNameTextFieldActionPerformed
* @param e The action listener
*/
public void setOKButtonActionListener(ActionListener e) {
OKButton.addActionListener(e);
}
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton OKButton; private javax.swing.JLabel caseDirField;
private javax.swing.JLabel caseDirLabel; private javax.swing.JLabel caseDirLabel;
private javax.swing.JTextArea caseDirTextArea;
private javax.swing.JLabel caseNameLabel; private javax.swing.JLabel caseNameLabel;
private javax.swing.JTextField caseNameTextField; private javax.swing.JTextField caseNameTextField;
private javax.swing.JLabel caseNumberField;
private javax.swing.JLabel caseNumberLabel; private javax.swing.JLabel caseNumberLabel;
private javax.swing.JTextField caseNumberTextField; private javax.swing.JLabel caseTypeField;
private javax.swing.JLabel casePropLabel; private javax.swing.JLabel crDateField;
private javax.swing.JLabel crDateLabel; private javax.swing.JLabel crDateLabel;
private javax.swing.JTextField crDateTextField; private javax.swing.JLabel dbNameField;
private javax.swing.JButton deleteCaseButton; private javax.swing.JButton deleteCaseButton;
private javax.swing.JLabel examinerField;
private javax.swing.JLabel examinerLabel; private javax.swing.JLabel examinerLabel;
private javax.swing.JTextField examinerTextField; private javax.swing.JPanel jPanel1;
private javax.swing.JLabel genInfoLabel;
private javax.swing.JTable imagesTable;
private javax.swing.JScrollPane imagesTableScrollPane;
private javax.swing.JLabel imgInfoLabel;
private javax.swing.JScrollPane jScrollPane1; private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextArea jTextArea1; private javax.swing.JTextArea jTextArea1;
private javax.swing.JLabel lbDbName; private javax.swing.JLabel lbDbName;
private javax.swing.JLabel lbDbType; private javax.swing.JLabel lbDbType;
private javax.swing.JTextField tbDbName;
private javax.swing.JTextField tbDbType;
private javax.swing.JButton updateCaseNameButton; private javax.swing.JButton updateCaseNameButton;
// End of variables declaration//GEN-END:variables // End of variables declaration//GEN-END:variables

View File

@ -25,17 +25,30 @@ import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskDataException;
/** /**
* Represents the blackboard, a place where artifacts and their attributes are * A representation of the blackboard, a place where artifacts and their
* posted. * attributes are posted.
* *
* NOTE: This API of this class is under development. * NOTE: This API of this class is under development.
*/ */
public final class Blackboard implements Closeable { public final class Blackboard implements Closeable {
private SleuthkitCase caseDb;
/**
* Constructs a representation of the blackboard, a place where artifacts
* and their attributes are posted.
*
* @param casedb The case database.
*/
Blackboard(SleuthkitCase casedb) {
this.caseDb = casedb;
}
/** /**
* Indexes the text associated with the an artifact. * Indexes the text associated with the an artifact.
* *
@ -43,7 +56,10 @@ public final class Blackboard implements Closeable {
* *
* @throws BlackboardException If there is a problem indexing the artifact. * @throws BlackboardException If there is a problem indexing the artifact.
*/ */
public void indexArtifact(BlackboardArtifact artifact) throws BlackboardException { public synchronized void indexArtifact(BlackboardArtifact artifact) throws BlackboardException {
if (null == caseDb) {
throw new BlackboardException("Blackboard has been closed");
}
KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class); KeywordSearchService searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
if (null == searchService) { if (null == searchService) {
throw new BlackboardException("Keyword search service not found"); throw new BlackboardException("Keyword search service not found");
@ -67,12 +83,15 @@ public final class Blackboard implements Closeable {
* @throws BlackboardBlackboardException If there is a problem getting or * @throws BlackboardBlackboardException If there is a problem getting or
* adding the artifact type. * adding the artifact type.
*/ */
public BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName) throws BlackboardException { public synchronized BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName) throws BlackboardException {
if (null == caseDb) {
throw new BlackboardException("Blackboard has been closed");
}
try { try {
return Case.getCurrentCase().getSleuthkitCase().addBlackboardArtifactType(typeName, displayName); return caseDb.addBlackboardArtifactType(typeName, displayName);
} catch (TskDataException typeExistsEx) { } catch (TskDataException typeExistsEx) {
try { try {
return Case.getCurrentCase().getSleuthkitCase().getArtifactType(typeName); return caseDb.getArtifactType(typeName);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add artifact type", ex); throw new BlackboardException("Failed to get or add artifact type", ex);
} }
@ -94,12 +113,15 @@ public final class Blackboard implements Closeable {
* @throws BlackboardBlackboardException If there is a problem getting or * @throws BlackboardBlackboardException If there is a problem getting or
* adding the attribute type. * adding the attribute type.
*/ */
public BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws BlackboardException { public synchronized BlackboardAttribute.Type getOrAddAttributeType(String typeName, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws BlackboardException {
if (null == caseDb) {
throw new BlackboardException("Blackboard has been closed");
}
try { try {
return Case.getCurrentCase().getSleuthkitCase().addArtifactAttributeType(typeName, valueType, displayName); return caseDb.addArtifactAttributeType(typeName, valueType, displayName);
} catch (TskDataException typeExistsEx) { } catch (TskDataException typeExistsEx) {
try { try {
return Case.getCurrentCase().getSleuthkitCase().getAttributeType(typeName); return caseDb.getAttributeType(typeName);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
throw new BlackboardException("Failed to get or add attribute type", ex); throw new BlackboardException("Failed to get or add attribute type", ex);
} }
@ -109,13 +131,16 @@ public final class Blackboard implements Closeable {
} }
/** /**
* Cloese this blackboard and releases any resources associated with it. * Closes the blackboard.
* @throws IOException *
* @throws IOException If there is a problem closing the blackboard.
*/ */
@Override @Override
public void close() throws IOException { public synchronized void close() throws IOException {
caseDb = null;
} }
/** /**
* A blackboard exception. * A blackboard exception.
*/ */

View File

@ -1,16 +1,3 @@
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.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.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1})
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset

View File

@ -1,16 +1,3 @@
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\u3092\u4f5c\u6210\u4e2d\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.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.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 TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset

View File

@ -1,19 +1,19 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* *
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com * Contact: aebadirad <at> 42six <dot> com
* Project Contact/Architect: carrier <at> sleuthkit <dot> org * Project Contact/Architect: 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");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -25,10 +25,9 @@ package org.sleuthkit.autopsy.casemodule.services;
import java.io.Closeable; import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
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.datamodel.VirtualDirectoryNode; import org.sleuthkit.autopsy.datamodel.VirtualDirectoryNode;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
@ -36,67 +35,102 @@ import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.DerivedFile;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.LocalFile;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction; import org.sleuthkit.datamodel.SleuthkitCase.CaseDbTransaction;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange; import org.sleuthkit.datamodel.TskFileRange;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
import org.sleuthkit.datamodel.CarvedFileContainer;
import org.sleuthkit.datamodel.LocalFilesDataSource; import org.sleuthkit.datamodel.LocalFilesDataSource;
import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.datamodel.TskDataException;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.datamodel.CarvingResult;
/** /**
* Abstraction to facilitate access to localFiles and directories. * A manager that provides methods for retrieving files from the current case
* and for adding local files, carved files, and derived files to the current
* case.
*/ */
public class FileManager implements Closeable { public class FileManager implements Closeable {
private SleuthkitCase tskCase; private SleuthkitCase caseDb;
private static final Logger logger = Logger.getLogger(FileManager.class.getName());
private volatile int curNumFileSets; //current number of filesets (root virt dir objects)
public FileManager(SleuthkitCase tskCase) {
this.tskCase = tskCase;
init();
}
/** /**
* initialize the file manager for the case * Constructs a manager that provides methods for retrieving files from the
* current case and for adding local files, carved files, and derived files
* to the current case.
*
* @param caseDb The case database.
*/ */
private synchronized void init() { public FileManager(SleuthkitCase caseDb) {
//get the number of local file sets in db this.caseDb = caseDb;
List<VirtualDirectory> virtRoots;
curNumFileSets = 0;
try {
virtRoots = tskCase.getVirtualDirectoryRoots();
for (VirtualDirectory vd : virtRoots) {
if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) {
++curNumFileSets;
}
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error initializing FileManager and getting number of local file sets"); //NON-NLS
}
} }
/** /**
* Finds a set of localFiles that meets the name criteria in all data * Finds all files with types that match one of a collection of MIME types.
* sources in the current case.
* *
* @param fileName Pattern of the name of the file or directory to match * @param mimeTypes The MIME types.
* (case insensitive, used in LIKE SQL statement).
* *
* @return a list of AbstractFile for localFiles/directories whose name * @return The files.
* matches the given fileName *
* @throws TskCoreException If there is a problem querying the case
* database.
*/
public synchronized List<AbstractFile> findFilesByMimeType(Collection<String> mimeTypes) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
}
return caseDb.findAllFilesWhere(createFileTypeInCondition(mimeTypes));
}
/**
* Finds all files in a given data source (image, local/logical files set,
* etc.) with types that match one of a collection of MIME types.
*
* @param dataSource The data source.
* @param mimeTypes The MIME types.
*
* @return The files.
*
* @throws TskCoreException If there is a problem querying the case
* database.
*/
public synchronized List<AbstractFile> findFilesByMimeType(Content dataSource, Collection<String> mimeTypes) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
}
return caseDb.findAllFilesWhere("data_source_obj_id = " + dataSource.getId() + " AND " + createFileTypeInCondition(mimeTypes));
}
/**
* Converts a list of MIME types into an SQL "mime_type IN" condition.
*
* @param mimeTypes The MIIME types.
*
* @return The condition string.
*/
private static String createFileTypeInCondition(Collection<String> mimeTypes) {
String types = StringUtils.join(mimeTypes, "', '");
return "mime_type IN ('" + types + "')";
}
/**
* Finds all files and directories with a given file name. The name search
* is for full or partial matches and is case insensitive (a case
* insensitive SQL LIKE clause is used to query the case database).
*
* @param fileName The full or partial file name.
*
* @return The matching files and directories.
*
* @throws TskCoreException if there is a problem querying the case
* database.
*/ */
public synchronized List<AbstractFile> findFiles(String fileName) throws TskCoreException { public synchronized List<AbstractFile> findFiles(String fileName) throws TskCoreException {
List<AbstractFile> result = new ArrayList<>(); if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
if (tskCase == null) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg"));
} }
List<Content> dataSources = tskCase.getRootObjects(); List<AbstractFile> result = new ArrayList<>();
List<Content> dataSources = caseDb.getRootObjects();
for (Content dataSource : dataSources) { for (Content dataSource : dataSources) {
result.addAll(findFiles(dataSource, fileName)); result.addAll(findFiles(dataSource, fileName));
} }
@ -104,290 +138,221 @@ public class FileManager implements Closeable {
} }
/** /**
* Finds a set of localFiles that meets the name criteria in all data * Finds all files and directories with a given file name and parent file or
* sources in the current case. * directory name. The name searches are for full or partial matches and are
* case insensitive (a case insensitive SQL LIKE clause is used to query the
* case database).
* *
* @param fileName Pattern of the name of the file or directory to match * @param fileName The full or partial file name.
* (case insensitive, used in LIKE SQL statement). * @param parentName The full or partial parent file or directory name.
* @param dirName Pattern of the name of the parent directory to use as the
* root of the search (case insensitive, used in LIKE SQL
* statement).
* *
* @return a list of AbstractFile for localFiles/directories whose name * @return The matching files and directories.
* matches fileName and whose parent directory contains dirName. *
* @throws TskCoreException if there is a problem querying the case
* database.
*/ */
public synchronized List<AbstractFile> findFiles(String fileName, String dirName) throws TskCoreException { public synchronized List<AbstractFile> findFiles(String fileName, String parentName) throws TskCoreException {
List<AbstractFile> result = new ArrayList<>(); if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
if (tskCase == null) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg"));
} }
List<Content> dataSources = tskCase.getRootObjects(); List<AbstractFile> result = new ArrayList<>();
List<Content> dataSources = caseDb.getRootObjects();
for (Content dataSource : dataSources) { for (Content dataSource : dataSources) {
result.addAll(findFiles(dataSource, fileName, dirName)); result.addAll(findFiles(dataSource, fileName, parentName));
} }
return result; return result;
} }
/** /**
* Finds a set of localFiles that meets the name criteria in all data * Finds all files and directories with a given file name and parent file or
* sources in the current case. * directory. The name search is for full or partial matches and is case
* insensitive (a case insensitive SQL LIKE clause is used to query the case
* database).
* *
* @param fileName Pattern of the name of the file or directory to match * @param fileName The full or partial file name.
* (case insensitive, used in LIKE SQL statement). * @param parent The parent file or directory.
* @param parentFile Object of root/parent directory to restrict search to.
* *
* @return a list of AbstractFile for localFiles/directories whose name * @return The matching files and directories.
* matches fileName and that were inside a directory described by *
* parentFsContent. * @throws TskCoreException if there is a problem querying the case
* database.
*/ */
public synchronized List<AbstractFile> findFiles(String fileName, AbstractFile parentFile) throws TskCoreException { public synchronized List<AbstractFile> findFiles(String fileName, AbstractFile parent) throws TskCoreException {
List<AbstractFile> result = new ArrayList<>(); if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
if (tskCase == null) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg"));
} }
List<Content> dataSources = tskCase.getRootObjects(); List<AbstractFile> result = new ArrayList<>();
List<Content> dataSources = caseDb.getRootObjects();
for (Content dataSource : dataSources) { for (Content dataSource : dataSources) {
result.addAll(findFiles(dataSource, fileName, parentFile)); result.addAll(findFiles(dataSource, fileName, parent));
} }
return result; return result;
} }
/** /**
* Finds a set of localFiles that meets the name criteria. * Finds all files and directories with a given file name in a given data
* source (image, local/logical files set, etc.). The name search is for
* full or partial matches and is case insensitive (a case insensitive SQL
* LIKE clause is used to query the case database).
* *
* @param dataSource Root data source to limit search results to (Image, * @param dataSource The data source.
* VirtualDirectory, etc.). * @param fileName The full or partial file name.
* @param fileName Pattern of the name of the file or directory to match
* (case insensitive, used in LIKE SQL statement).
* *
* @return a list of AbstractFile for localFiles/directories whose name * @return The matching files and directories.
* matches the given fileName *
* @throws TskCoreException if there is a problem querying the case
* database.
*/ */
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 (null == caseDb) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles.exception.msg")); throw new TskCoreException("File manager has been closed");
} }
return tskCase.findFiles(dataSource, fileName); return caseDb.findFiles(dataSource, fileName);
} }
/** /**
* Finds a set of localFiles that meets the name criteria. * Finds all files and directories with a given file name and parent file or
* directory name in a given data source (image, local/logical files set,
* etc.). The name searches are for full or partial matches and are case
* insensitive (a case insensitive SQL LIKE clause is used to query the case
* database).
* *
* @param dataSource Root data source to limit search results to (Image, * @param dataSource The data source.
* VirtualDirectory, etc.). * @param fileName The full or partial file name.
* @param fileName Pattern of the name of the file or directory to match * @param parentName The full or partial parent file or directory name.
* (case insensitive, used in LIKE SQL statement).
* @param dirName Pattern of the name of the parent directory to use as
* the root of the search (case insensitive, used in LIKE
* SQL statement).
* *
* @return a list of AbstractFile for localFiles/directories whose name * @return The matching files and directories.
* matches fileName and whose parent directory contains dirName. *
* @throws TskCoreException if there is a problem querying the case
* database.
*/ */
public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, String dirName) throws TskCoreException { public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, String parentName) throws TskCoreException {
if (tskCase == null) { if (null == caseDb) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles2.exception.msg")); throw new TskCoreException("File manager has been closed");
} }
return tskCase.findFiles(dataSource, fileName, dirName); return caseDb.findFiles(dataSource, fileName, parentName);
} }
/** /**
* Finds a set of localFiles that meets the name criteria. * Finds all files and directories with a given file name and given parent
* file or directory in a given data source (image, local/logical files set,
* etc.). The name search is for full or partial matches and is case
* insensitive (a case insensitive SQL LIKE clause is used to query the case
* database).
* *
* @param dataSource Root data source to limit search results to (Image, * @param dataSource The data source.
* VirtualDirectory, etc.). * @param fileName The full or partial file name.
* @param fileName Pattern of the name of the file or directory to match * @param parent The parent file or directory.
* (case insensitive, used in LIKE SQL statement).
* @param parentFile Object of root/parent directory to restrict search to.
* *
* @return a list of AbstractFile for localFiles/directories whose name * @return The matching files and directories.
* matches fileName and that were inside a directory described by *
* parentFsContent. * @throws TskCoreException if there is a problem querying the case
* database.
*/ */
public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException { public synchronized List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parent) throws TskCoreException {
if (tskCase == null) { if (null == caseDb) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.findFiles3.exception.msg")); throw new TskCoreException("File manager has been closed");
} }
return findFiles(dataSource, fileName, parentFile.getName()); return findFiles(dataSource, fileName, parent.getName());
} }
/** /**
* @param dataSource data source Content (Image, parent-less * Finds all files and directories with a given file name and path in a
* VirtualDirectory) where to find localFiles * given data source (image, local/logical files set, etc.). The name search
* @param filePath The full path to the file(s) of interest. This can * is for full or partial matches and is case insensitive (a case
* optionally include the image and volume names. * insensitive SQL LIKE clause is used to query the case database). Any path
* components at the volume level and above are removed for the search.
* *
* @return a list of AbstractFile that have the given file path. * @param dataSource The data source.
* @param fileName The full or partial file name.
* @param filePath The file path (path components volume at the volume
* level or above will be removed).
*
* @return The matching files and directories.
*
* @throws TskCoreException if there is a problem querying the case
* database.
*/ */
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 (null == caseDb) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.openFiles.exception.msg")); throw new TskCoreException("File manager has been closed");
} }
return tskCase.openFiles(dataSource, filePath); return caseDb.openFiles(dataSource, filePath);
} }
/** /**
* Creates a derived file, adds it to the database and returns it. * Adds a derived file to the case.
* *
* @param fileName file name the derived file * @param fileName The name of the file.
* @param localPath local path of the derived file, including the file * @param localPath The local path of the file, relative to the case
* name. The path is relative to the case folder. * folder and including the file name.
* @param size size of the derived file in bytes * @param size The size of the file in bytes.
* @param ctime * @param ctime The change time of the file.
* @param crtime * @param crtime The create time of the file
* @param atime * @param atime The accessed time of the file.
* @param mtime * @param mtime The modified time of the file.
* @param isFile whether a file or directory, true if a file * @param isFile True if a file, false if a directory.
* @param parentFile the parent file object this the new file was * @param parentFile The parent file from which the file was derived.
* derived from, either a fs file or parent derived * @param rederiveDetails The details needed to re-derive file (will be
* file/dikr\\r * specific to the derivation method), currently
* @param rederiveDetails details needed to re-derive file (will be specific * unused.
* to the derivation method), currently unused * @param toolName The name of the derivation method or tool,
* @param toolName name of derivation method/tool, currently unused * currently unused.
* @param toolVersion version of derivation method/tool, currently * @param toolVersion The version of the derivation method or tool,
* unused * currently unused.
* @param otherDetails details of derivation method/tool, currently * @param otherDetails Other details of the derivation method or tool,
* unused * currently unused.
* *
* @return newly created derived file object added to the database * @return A DerivedFile object representing the derived file.
*
* @throws TskCoreException exception thrown if the object creation failed
* due to a critical system error or of the file
* manager has already been closed
* *
* @throws TskCoreException if there is a problem adding the file to the
* case database.
*/ */
public synchronized DerivedFile addDerivedFile(String fileName, String localPath, long size, public synchronized DerivedFile addDerivedFile(String fileName,
String localPath,
long size,
long ctime, long crtime, long atime, long mtime, long ctime, long crtime, long atime, long mtime,
boolean isFile, AbstractFile parentFile, boolean isFile,
AbstractFile parentFile,
String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException { String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException {
if (null == caseDb) {
if (tskCase == null) { throw new TskCoreException("File manager has been closed");
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addDerivedFile.exception.msg"));
} }
return caseDb.addDerivedFile(fileName, localPath, size,
return tskCase.addDerivedFile(fileName, localPath, size,
ctime, crtime, atime, mtime, ctime, crtime, atime, mtime,
isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails); isFile, parentFile, rederiveDetails, toolName, toolVersion, otherDetails);
} }
/** /**
* Adds a carved file to the VirtualDirectory '$CarvedFiles' in the volume * Adds a carving result to the case database.
* or image given by systemId.
* *
* @param carvedFileName the name of the carved file (containing appropriate * @param carvingResult The carving result (a set of carved files and their
* extension) * parent) to be added.
* @param carvedFileSize size of the carved file to add
* @param systemId the ID of the parent volume or file system
* @param sectors a list of SectorGroups giving this sectors that
* make up this carved file.
* *
* @throws TskCoreException exception thrown when critical tsk error * @return A list of LayoutFile representations of the carved files.
* occurred and carved file could not be added *
* @throws TskCoreException If there is a problem completing a case database
* operation.
*/ */
public synchronized LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, public synchronized List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws TskCoreException {
long systemId, List<TskFileRange> sectors) throws TskCoreException { if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
if (tskCase == null) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg"));
} }
return caseDb.addCarvedFiles(carvingResult);
return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, sectors);
} }
/** /**
* Adds a collection of carved localFiles to the VirtualDirectory * Interface for receiving a notification for each file or directory added
* '$CarvedFiles' in the volume or image given by systemId. Creates * to the case database by a FileManager add files operation.
* $CarvedFiles if it does not exist already.
*
* @param filesToAdd a list of CarvedFileContainer localFiles to add as
* carved localFiles
*
* @return List<LayoutFile> This is a list of the localFiles added to the
* database
*
* @throws org.sleuthkit.datamodel.TskCoreException
*/
public List<LayoutFile> addCarvedFiles(List<CarvedFileContainer> filesToAdd) throws TskCoreException {
if (tskCase == null) {
throw new TskCoreException(NbBundle.getMessage(this.getClass(), "FileManager.addCarvedFile.exception.msg"));
} else {
return tskCase.addCarvedFiles(filesToAdd);
}
}
/**
*
* Interface for receiving notifications on folders being added via a
* callback
*/ */
public interface FileAddProgressUpdater { public interface FileAddProgressUpdater {
/** /**
* Called when new folders has been added * Called after a file or directory is added to the case database.
* *
* @param newFile the file/folder added to the Case * @param An AbstractFile represeting the added file or directory.
*/ */
public void fileAdded(AbstractFile newFile); void fileAdded(AbstractFile newFile);
}
/**
* Add a set of local/logical localFiles and dirs.
*
* @param localAbsPaths list of absolute paths to local localFiles and
* dirs
* @param addProgressUpdater notifier to receive progress notifications on
* folders added, or null if not used
*
* @return file set root VirtualDirectory contained containing all
* AbstractFile objects added
*
* @throws TskCoreException exception thrown if the object creation failed
* due to a critical system error or of the file
* manager has already been closed. There is no
* "revert" logic if one of the additions fails.
* The addition stops with the first error
* encountered.
*/
public synchronized VirtualDirectory addLocalFilesDirs(List<String> localAbsPaths, FileAddProgressUpdater addProgressUpdater) throws TskCoreException {
List<java.io.File> rootsToAdd;
try {
rootsToAdd = getFilesAndDirectories(localAbsPaths);
} catch (TskDataException ex) {
throw new TskCoreException(ex.getLocalizedMessage(), ex);
}
CaseDbTransaction trans = tskCase.beginTransaction();
// make a virtual top-level directory for this set of localFiles/dirs
final VirtualDirectory fileSetRootDir = addLocalFileSetRootDir(trans);
try {
// recursively add each item in the set
for (java.io.File localRootToAdd : rootsToAdd) {
AbstractFile localFileAdded = addLocalDirInt(trans, fileSetRootDir, localRootToAdd, addProgressUpdater);
if (localFileAdded == null) {
String msg = NbBundle
.getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.cantAdd.msg",
localRootToAdd.getAbsolutePath());
logger.log(Level.SEVERE, msg);
throw new TskCoreException(msg);
} else {
//added.add(localFileAdded);
//send new content event
//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
// since the transaction is not yet committed.
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(localFileAdded));
}
}
trans.commit();
} catch (TskCoreException ex) {
trans.rollback();
}
return fileSetRootDir;
} }
/** /**
@ -419,20 +384,27 @@ public class FileManager implements Closeable {
* directory that does not exist or cannot be read. * directory that does not exist or cannot be read.
*/ */
public synchronized LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootVirtualDirectoryName, String timeZone, List<String> localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException, TskDataException { public synchronized LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootVirtualDirectoryName, String timeZone, List<String> localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException, TskDataException {
if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
}
List<java.io.File> localFiles = getFilesAndDirectories(localFilePaths); List<java.io.File> localFiles = getFilesAndDirectories(localFilePaths);
CaseDbTransaction trans = null; CaseDbTransaction trans = null;
try { try {
String rootDirectoryName = rootVirtualDirectoryName; String rootDirectoryName = rootVirtualDirectoryName;
int newLocalFilesSetCount = curNumFileSets + 1; if (rootDirectoryName.isEmpty()) {
if (rootVirtualDirectoryName.isEmpty()) { rootDirectoryName = generateFilesDataSourceName(caseDb);
rootDirectoryName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newLocalFilesSetCount;
} }
trans = tskCase.beginTransaction();
LocalFilesDataSource dataSource = tskCase.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans); /*
* Add the root virtual directory and its local/logical file
* children to the case database.
*/
trans = caseDb.beginTransaction();
LocalFilesDataSource dataSource = caseDb.addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, trans);
VirtualDirectory rootDirectory = dataSource.getRootDirectory(); VirtualDirectory rootDirectory = dataSource.getRootDirectory();
List<AbstractFile> filesAdded = new ArrayList<>(); List<AbstractFile> filesAdded = new ArrayList<>();
for (java.io.File localFile : localFiles) { for (java.io.File localFile : localFiles) {
AbstractFile fileAdded = addLocalDirInt(trans, rootDirectory, localFile, progressUpdater); AbstractFile fileAdded = addLocalFile(trans, rootDirectory, localFile, progressUpdater);
if (null != fileAdded) { if (null != fileAdded) {
filesAdded.add(fileAdded); filesAdded.add(fileAdded);
} else { } else {
@ -440,13 +412,16 @@ public class FileManager implements Closeable {
} }
} }
trans.commit(); trans.commit();
if (rootVirtualDirectoryName.isEmpty()) {
curNumFileSets = newLocalFilesSetCount; /*
} * Publish content added events for the added files and directories.
*/
for (AbstractFile fileAdded : filesAdded) { for (AbstractFile fileAdded : filesAdded) {
IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(fileAdded)); IngestServices.getInstance().fireModuleContentEvent(new ModuleContentEvent(fileAdded));
} }
return dataSource; return dataSource;
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
if (null != trans) { if (null != trans) {
trans.rollback(); trans.rollback();
@ -455,6 +430,34 @@ public class FileManager implements Closeable {
} }
} }
/**
* Generates a name for the root virtual directory for the data source.
*
* NOTE: Although this method is guarded by the file manager's monitor,
* there is currently a minimal chance of default name duplication for
* multi-user cases with multiple FileManagers running on different nodes.
*
* @return A default name for a local/logical files data source of the form:
* LogicalFileSet[N].
*
* @throws TskCoreException If there is a problem querying the case
* database.
*/
private static synchronized String generateFilesDataSourceName(SleuthkitCase caseDb) throws TskCoreException {
int localFileDataSourcesCounter = 0;
try {
List<VirtualDirectory> localFileDataSources = caseDb.getVirtualDirectoryRoots();
for (VirtualDirectory vd : localFileDataSources) {
if (vd.getName().startsWith(VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX)) {
++localFileDataSourcesCounter;
}
}
return VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + (localFileDataSourcesCounter + 1);
} catch (TskCoreException ex) {
throw new TskCoreException("Error querying for existing local file data sources with defualt names", ex);
}
}
/** /**
* Converts a list of local/logical file and/or directory paths to a list of * Converts a list of local/logical file and/or directory paths to a list of
* file objects. * file objects.
@ -472,7 +475,7 @@ public class FileManager implements Closeable {
for (String path : localFilePaths) { for (String path : localFilePaths) {
java.io.File localFile = new java.io.File(path); java.io.File localFile = new java.io.File(path);
if (!localFile.exists() || !localFile.canRead()) { if (!localFile.exists() || !localFile.canRead()) {
throw new TskDataException(NbBundle.getMessage(this.getClass(), "FileManager.addLocalFilesDirs.exception.notReadable.msg", localFile.getAbsolutePath())); throw new TskDataException(String.format("File at %s does not exist or cannot be read", localFile.getAbsolutePath()));
} }
localFiles.add(localFile); localFiles.add(localFile);
} }
@ -480,130 +483,141 @@ public class FileManager implements Closeable {
} }
/** /**
* Adds a new virtual directory root object with FileSet X name and * Adds a file or directory of logical/local files data source to the case
* consecutive sequence number characteristic to every add operation * database, recursively adding the contents of directories.
*
* @return the virtual dir root container created
*
* @throws TskCoreException
*/
private VirtualDirectory addLocalFileSetRootDir(CaseDbTransaction trans) throws TskCoreException {
VirtualDirectory created = null;
int newFileSetCount = curNumFileSets + 1;
final String fileSetName = VirtualDirectoryNode.LOGICAL_FILE_SET_PREFIX + newFileSetCount;
try {
created = tskCase.addVirtualDirectory(0, fileSetName, trans);
curNumFileSets = newFileSetCount;
} catch (TskCoreException ex) {
String msg = NbBundle
.getMessage(this.getClass(), "FileManager.addLocalFileSetRootDir.exception.errCreateDir.msg",
fileSetName);
logger.log(Level.SEVERE, msg, ex);
throw new TskCoreException(msg, ex);
}
return created;
}
/**
* Helper (internal) method to recursively add contents of a folder. Node
* passed in can be a file or directory. Children of directories are added.
* *
* @param trans A case database transaction. * @param trans A case database transaction.
* @param parentVd Dir that is the parent of localFile * @param parentDirectory The root virtual direcotry of the data source.
* @param localFile File/Dir that we are adding * @param localFile The local/logical file or directory.
* @param addProgressUpdater notifier to receive progress notifications on * @param addProgressUpdater notifier to receive progress notifications on
* folders added, or null if not used * folders added, or null if not used
* *
* @returns File object of file added or new virtualdirectory for the * @returns File object of file added or new virtualdirectory for the
* directory. * directory.
* @throws TskCoreException * @param progressUpdater Called after each file/directory is added to
* the case database.
*
* @return An AbstractFile representation of the local/logical file.
*
* @throws TskCoreException If there is a problem completing a database
* operation.
*/ */
private AbstractFile addLocalDirInt(CaseDbTransaction trans, VirtualDirectory parentVd, private AbstractFile addLocalFile(CaseDbTransaction trans, VirtualDirectory parentDirectory, java.io.File localFile, FileAddProgressUpdater progressUpdater) throws TskCoreException {
java.io.File localFile, FileAddProgressUpdater addProgressUpdater) throws TskCoreException {
if (tskCase == null) {
throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.closed.msg"));
}
//final String localName = localDir.getName();
if (!localFile.exists()) {
throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.doesntExist.msg",
localFile.getAbsolutePath()));
}
if (!localFile.canRead()) {
throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt.exception.notReadable.msg",
localFile.getAbsolutePath()));
}
if (localFile.isDirectory()) { if (localFile.isDirectory()) {
//create virtual folder (we don't have a notion of a 'local folder') /*
final VirtualDirectory childVd = tskCase.addVirtualDirectory(parentVd.getId(), localFile.getName(), trans); * Add the directory as a virtual directory.
if (childVd != null && addProgressUpdater != null) { */
addProgressUpdater.fileAdded(childVd); VirtualDirectory virtualDirectory = caseDb.addVirtualDirectory(parentDirectory.getId(), localFile.getName(), trans);
} progressUpdater.fileAdded(virtualDirectory);
//add children recursively
final java.io.File[] childrenFiles = localFile.listFiles(); /*
if (childrenFiles != null) { * Add its children, if any.
for (java.io.File childFile : childrenFiles) { */
addLocalDirInt(trans, childVd, childFile, addProgressUpdater); final java.io.File[] childFiles = localFile.listFiles();
if (childFiles != null && childFiles.length > 0) {
for (java.io.File childFile : childFiles) {
addLocalFile(trans, virtualDirectory, childFile, progressUpdater);
} }
} }
return childVd;
return virtualDirectory;
} else { } else {
//add leaf file, base case return caseDb.addLocalFile(localFile.getName(), localFile.getAbsolutePath(), localFile.length(),
return this.addLocalFileInt(parentVd, localFile, trans); 0, 0, 0, 0,
localFile.isFile(), parentDirectory, trans);
} }
} }
/** /**
* Adds a single local/logical file to the case. Adds it to the database. * Closes the file manager.
* Does not refresh the views of data. Assumes that the local file exists
* and can be read. This checking is done by addLocalDirInt().
* *
* @param parentFile parent file object container (such as virtual * @throws IOException If there is a problem closing the file manager.
* directory, another local file, or fscontent File),
* @param localFile File that we are adding
* @param trans A case database transaction.
*
* @return newly created local file object added to the database
*
* @throws TskCoreException exception thrown if the object creation failed
* due to a critical system error or of the file
* manager has already been closed
*/ */
private synchronized LocalFile addLocalFileInt(AbstractFile parentFile, java.io.File localFile, CaseDbTransaction trans) throws TskCoreException {
if (tskCase == null) {
throw new TskCoreException(
NbBundle.getMessage(this.getClass(), "FileManager.addLocalDirInt2.exception.closed.msg"));
}
long size = localFile.length();
boolean isFile = localFile.isFile();
long ctime = 0;
long crtime = 0;
long atime = 0;
long mtime = 0;
String fileName = localFile.getName();
LocalFile lf = tskCase.addLocalFile(fileName, localFile.getAbsolutePath(), size,
ctime, crtime, atime, mtime,
isFile, parentFile, trans);
return lf;
}
@Override @Override
public synchronized void close() throws IOException { public synchronized void close() throws IOException {
tskCase = null; caseDb = null;
} }
/**
* Adds a set of local/logical files and/or directories to the case database
* as data source.
*
* @param localFilePaths A list of local/logical file and/or directory
* localFilePaths.
* @param progressUpdater Called after each file/directory is added to the
* case database.
*
* @return The root virtual directory for the local/logical files data
* source.
*
* @throws TskCoreException If any of the local file paths is for a file or
* directory that does not exist or cannot be read,
* or there is a problem completing a database
* operation.
* @deprecated Use addLocalFilesDataSource instead.
*/
@Deprecated
public synchronized VirtualDirectory addLocalFilesDirs(List<String> localFilePaths, FileAddProgressUpdater progressUpdater) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
}
try {
return addLocalFilesDataSource("", "", "", localFilePaths, progressUpdater).getRootDirectory();
} catch (TskDataException ex) {
throw new TskCoreException(ex.getLocalizedMessage(), ex);
}
}
/**
* Adds a carved file to the '$CarvedFiles' virtual directory of a data
* source, volume or file system.
*
* @param fileName The name of the file.
* @param fileSize The size of the file.
* @param parentObjId The object id of the parent data source, volume or
* file system.
* @param layout A list of the offsets and sizes that gives the layout
* of the file within its parent.
*
* @return A LayoutFile object representing the carved file.
*
* @throws TskCoreException if there is a problem adding the file to the
* case database.
* @deprecated Use List<LayoutFile> addCarvedFiles(CarvingResult
* carvingResult instead.
*/
@Deprecated
public synchronized LayoutFile addCarvedFile(String fileName, long fileSize, long parentObjId, List<TskFileRange> layout) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
}
Content parent = caseDb.getContentById(parentObjId);
List<CarvingResult.CarvedFile> carvedFiles = new ArrayList<>();
carvedFiles.add(new CarvingResult.CarvedFile(fileName, fileSize, layout));
List<LayoutFile> layoutFiles = caseDb.addCarvedFiles(new CarvingResult(parent, carvedFiles));
return layoutFiles.get(0);
}
/**
* Adds a collection of carved files to the '$CarvedFiles' virtual directory
* of a data source, volume or file system.
*
* @param A collection of CarvedFileContainer objects, one per carved file,
* all of which must have the same parent object id.
*
* @return A collection of LayoutFile object representing the carved files.
*
* @throws TskCoreException if there is a problem adding the files to the
* case database.
* @deprecated Use List<LayoutFile> addCarvedFiles(CarvingResult
* carvingResult instead.
*/
@Deprecated
public synchronized List<LayoutFile> addCarvedFiles(List<org.sleuthkit.datamodel.CarvedFileContainer> filesToAdd) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("File manager has been closed");
}
return caseDb.addCarvedFiles(filesToAdd);
}
} }

View File

@ -1,19 +1,18 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-2015 Basis Technology Corp. * Copyright 2011-2016 Basis Technology Corp.
* * Contact: carrier <at> sleuthkit <dot> org
* Copyright 2012 42six Solutions. * Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com * Contact: aebadirad <at> 42six <dot> com
* Project Contact/Architect: 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");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@ -31,7 +30,8 @@ import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
/** /**
* A class to manage various services. * A collection of case-level services (e.g., file manager, tags manager,
* keyword search, blackboard).
*/ */
public class Services implements Closeable { public class Services implements Closeable {
@ -41,36 +41,67 @@ public class Services implements Closeable {
private final KeywordSearchService keywordSearchService; private final KeywordSearchService keywordSearchService;
private final Blackboard blackboard; private final Blackboard blackboard;
public Services(SleuthkitCase tskCase) { /**
fileManager = new FileManager(tskCase); * Constructs a collection of case-level services (e.g., file manager, tags
* manager, keyword search, blackboard).
*
* @param caseDb The case database for the current case.
*/
public Services(SleuthkitCase caseDb) {
fileManager = new FileManager(caseDb);
services.add(fileManager); services.add(fileManager);
tagsManager = new TagsManager(tskCase); tagsManager = new TagsManager(caseDb);
services.add(tagsManager); services.add(tagsManager);
keywordSearchService = Lookup.getDefault().lookup(KeywordSearchService.class); keywordSearchService = Lookup.getDefault().lookup(KeywordSearchService.class);
services.add(keywordSearchService); services.add(keywordSearchService);
blackboard = new Blackboard(); blackboard = new Blackboard(caseDb);
services.add(blackboard); services.add(blackboard);
} }
/**
* Gets the file manager service for the current case.
*
* @return The file manager service for the current case.
*/
public FileManager getFileManager() { public FileManager getFileManager() {
return fileManager; return fileManager;
} }
/**
* Gets the tags manager service for the current case.
*
* @return The tags manager service for the current case.
*/
public TagsManager getTagsManager() { public TagsManager getTagsManager() {
return tagsManager; return tagsManager;
} }
/**
* Gets the keyword search service for the current case.
*
* @return The keyword search service for the current case.
*/
public KeywordSearchService getKeywordSearchService() { public KeywordSearchService getKeywordSearchService() {
return keywordSearchService; return keywordSearchService;
} }
/**
* Gets the blackboard service for the current case.
*
* @return The blackboard service for the current case.
*/
public Blackboard getBlackboard() { public Blackboard getBlackboard() {
return blackboard; return blackboard;
} }
/**
* Closes the services for the current case.
*
* @throws IOException if there is a problem closing the services.
*/
@Override @Override
public void close() throws IOException { public void close() throws IOException {
for (Closeable service : services) { for (Closeable service : services) {

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-16 Basis Technology Corp. * Copyright 2011-2016 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");
@ -45,7 +45,7 @@ public class TagsManager implements Closeable {
private static final Logger logger = Logger.getLogger(TagsManager.class.getName()); private static final Logger logger = Logger.getLogger(TagsManager.class.getName());
private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS private static final String TAGS_SETTINGS_NAME = "Tags"; //NON-NLS
private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS private static final String TAG_NAMES_SETTING_KEY = "TagNames"; //NON-NLS
private final SleuthkitCase caseDb; private SleuthkitCase caseDb;
private final HashMap<String, TagName> uniqueTagNames = new HashMap<>(); private final HashMap<String, TagName> uniqueTagNames = new HashMap<>();
private boolean tagNamesLoaded = false; private boolean tagNamesLoaded = false;
@ -53,8 +53,8 @@ public class TagsManager implements Closeable {
* Constructs a per case Autopsy service that manages the creation, * Constructs a per case Autopsy service that manages the creation,
* updating, and deletion of tags applied to content and blackboard * updating, and deletion of tags applied to content and blackboard
* artifacts by users. * artifacts by users.
* *
* @param caseDb The case database for the current case. * @param caseDb The case database.
*/ */
TagsManager(SleuthkitCase caseDb) { TagsManager(SleuthkitCase caseDb) {
this.caseDb = caseDb; this.caseDb = caseDb;
@ -70,6 +70,9 @@ public class TagsManager implements Closeable {
* database. * database.
*/ */
public synchronized List<TagName> getAllTagNames() throws TskCoreException { public synchronized List<TagName> getAllTagNames() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getAllTagNames(); return caseDb.getAllTagNames();
} }
@ -84,6 +87,9 @@ public class TagsManager implements Closeable {
* database. * database.
*/ */
public synchronized List<TagName> getTagNamesInUse() throws TskCoreException { public synchronized List<TagName> getTagNamesInUse() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getTagNamesInUse(); return caseDb.getTagNamesInUse();
} }
@ -114,6 +120,9 @@ public class TagsManager implements Closeable {
* to the case database. * to the case database.
*/ */
public TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException { public TagName addTagName(String displayName) throws TagNameAlreadyExistsException, TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addTagName(displayName, "", TagName.HTML_COLOR.NONE); return addTagName(displayName, "", TagName.HTML_COLOR.NONE);
} }
@ -132,6 +141,9 @@ public class TagsManager implements Closeable {
* to the case database. * to the case database.
*/ */
public TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException { public TagName addTagName(String displayName, String description) throws TagNameAlreadyExistsException, TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addTagName(displayName, description, TagName.HTML_COLOR.NONE); return addTagName(displayName, description, TagName.HTML_COLOR.NONE);
} }
@ -151,6 +163,9 @@ public class TagsManager implements Closeable {
* to the case database. * to the case database.
*/ */
public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException { public synchronized TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TagNameAlreadyExistsException, TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
if (uniqueTagNames.containsKey(displayName)) { if (uniqueTagNames.containsKey(displayName)) {
throw new TagNameAlreadyExistsException(); throw new TagNameAlreadyExistsException();
@ -182,6 +197,9 @@ public class TagsManager implements Closeable {
* database. * database.
*/ */
public ContentTag addContentTag(Content content, TagName tagName) throws TskCoreException { public ContentTag addContentTag(Content content, TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addContentTag(content, tagName, "", -1, -1); return addContentTag(content, tagName, "", -1, -1);
} }
@ -198,6 +216,9 @@ public class TagsManager implements Closeable {
* database. * database.
*/ */
public ContentTag addContentTag(Content content, TagName tagName, String comment) throws TskCoreException { public ContentTag addContentTag(Content content, TagName tagName, String comment) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addContentTag(content, tagName, comment, -1, -1); return addContentTag(content, tagName, comment, -1, -1);
} }
@ -218,10 +239,17 @@ public class TagsManager implements Closeable {
* the case database. * the case database.
*/ */
public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws IllegalArgumentException, TskCoreException { public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws IllegalArgumentException, TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
ContentTag tag; ContentTag tag;
synchronized (this) { synchronized (this) {
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
if (null == comment) {
throw new IllegalArgumentException("Passed null comment argument");
}
if (beginByteOffset >= 0 && endByteOffset >= 1) { if (beginByteOffset >= 0 && endByteOffset >= 1) {
if (beginByteOffset > content.getSize() - 1) { if (beginByteOffset > content.getSize() - 1) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(), throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
@ -261,6 +289,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public void deleteContentTag(ContentTag tag) throws TskCoreException { public void deleteContentTag(ContentTag tag) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
synchronized (this) { synchronized (this) {
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
caseDb.deleteContentTag(tag); caseDb.deleteContentTag(tag);
@ -282,6 +313,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<ContentTag> getAllContentTags() throws TskCoreException { public synchronized List<ContentTag> getAllContentTags() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getAllContentTags(); return caseDb.getAllContentTags();
} }
@ -297,6 +331,9 @@ public class TagsManager implements Closeable {
* the case database. * the case database.
*/ */
public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException { public synchronized long getContentTagsCountByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getContentTagsCountByTagName(tagName); return caseDb.getContentTagsCountByTagName(tagName);
} }
@ -312,6 +349,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException { public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getContentTagByID(tagID); return caseDb.getContentTagByID(tagID);
} }
@ -328,6 +368,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException { public synchronized List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getContentTagsByTagName(tagName); return caseDb.getContentTagsByTagName(tagName);
} }
@ -344,6 +387,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException { public synchronized List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getContentTagsByContent(content); return caseDb.getContentTagsByContent(content);
} }
@ -361,6 +407,9 @@ public class TagsManager implements Closeable {
* database. * database.
*/ */
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException { public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
return addBlackboardArtifactTag(artifact, tagName, ""); return addBlackboardArtifactTag(artifact, tagName, "");
} }
@ -378,9 +427,15 @@ public class TagsManager implements Closeable {
* database. * database.
*/ */
public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException { public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
BlackboardArtifactTag tag; BlackboardArtifactTag tag;
synchronized (this) { synchronized (this) {
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
if (null == comment) {
throw new IllegalArgumentException("Passed null comment argument");
}
tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment); tag = caseDb.addBlackboardArtifactTag(artifact, tagName, comment);
} }
@ -401,6 +456,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException { public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
synchronized (this) { synchronized (this) {
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
caseDb.deleteBlackboardArtifactTag(tag); caseDb.deleteBlackboardArtifactTag(tag);
@ -422,6 +480,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException { public synchronized List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getAllBlackboardArtifactTags(); return caseDb.getAllBlackboardArtifactTags();
} }
@ -438,6 +499,9 @@ public class TagsManager implements Closeable {
* the case database. * the case database.
*/ */
public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException { public synchronized long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsCountByTagName(tagName); return caseDb.getBlackboardArtifactTagsCountByTagName(tagName);
} }
@ -453,6 +517,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException { public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagByID(tagID); return caseDb.getBlackboardArtifactTagByID(tagID);
} }
@ -469,6 +536,9 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException { public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsByTagName(tagName); return caseDb.getBlackboardArtifactTagsByTagName(tagName);
} }
@ -485,16 +555,25 @@ public class TagsManager implements Closeable {
* case database. * case database.
*/ */
public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException { public synchronized List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException {
if (null == caseDb) {
throw new TskCoreException("Tags manager has been closed");
}
lazyLoadExistingTagNames(); lazyLoadExistingTagNames();
return caseDb.getBlackboardArtifactTagsByArtifact(artifact); return caseDb.getBlackboardArtifactTagsByArtifact(artifact);
} }
/** /**
* Saves the avaialble tag names to secondary storage. * Closes the tags manager, saving the avaialble tag names to secondary
* storage.
*
* @throws IOException If there is a problem closing the tags manager.
* @deprecated Tags manager clients should not close the tags manager.
*/ */
@Override @Override
@Deprecated
public synchronized void close() throws IOException { public synchronized void close() throws IOException {
saveTagNamesToTagsSettings(); saveTagNamesToTagsSettings();
caseDb = null;
} }
/** /**

View File

@ -5,12 +5,12 @@
<!-- ====================================================== <!-- ======================================================
General General
====================================================== --> ====================================================== -->
<attr name="Toolbars\File\org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance\iconBase" stringvalue="org/sleuthkit/autopsy/images/close-icon.gif"/> <attr name="Toolbars\Case\org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance\iconBase" stringvalue="org/sleuthkit/autopsy/images/close-icon.gif"/>
<attr name="Menu\File\org-netbeans-modules-print-action-PageSetupAction.shadow_hidden\position" intvalue="300"/> <attr name="Menu\Case\org-netbeans-modules-print-action-PageSetupAction.shadow_hidden\position" intvalue="300"/>
<attr name="Menu\File\org-netbeans-modules-print-action-PrintAction.shadow_hidden\position" intvalue="500"/> <attr name="Menu\Case\org-netbeans-modules-print-action-PrintAction.shadow_hidden\position" intvalue="500"/>
<!--<attr name="Menu\File\Separator2.instance_hidden\position" intvalue="100"/> <!--<attr name="Menu\Case\Separator2.instance_hidden\position" intvalue="100"/>
<attr name="Menu\File\Separator3.instance_hidden\position" intvalue="200"/> <attr name="Menu\Case\Separator3.instance_hidden\position" intvalue="200"/>
<attr name="Menu\File\Separator4.instance_hidden\position" intvalue="400"/>--> <attr name="Menu\Case\Separator4.instance_hidden\position" intvalue="400"/>-->
<folder name="OptionsDialog"> <folder name="OptionsDialog">
<!--<folder name="General.instance_hidden"/>--> <!--<folder name="General.instance_hidden"/>-->
@ -39,7 +39,7 @@
Actions Actions
====================================================== --> ====================================================== -->
<folder name="Actions"> <folder name="Actions">
<folder name="File"> <folder name="Case">
<file name="org-sleuthkit-autopsy-casemodule-AddImageAction.instance"/> <file name="org-sleuthkit-autopsy-casemodule-AddImageAction.instance"/>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/> <file name="org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/>
<file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"> <file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.instance">
@ -145,24 +145,25 @@
<file name="GoTo_hidden"/> <file name="GoTo_hidden"/>
<file name="Reports_hidden"/> <file name="Reports_hidden"/>
<file name="Edit_hidden"/> <file name="Edit_hidden"/>
<folder name="File"> <file name="File_hidden"/>
<folder name="Case">
<file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"/>
<attr name="position" intvalue="100"/> <attr name="position" intvalue="100"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-CaseOpenAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/>
<attr name="position" intvalue="101"/> <attr name="position" intvalue="101"/>
</file> </file>
<folder name="OpenRecentCase"> <folder name="Open Recent Case">
<attr name="position" intvalue="102"/> <attr name="position" intvalue="102"/>
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.sleuthkit.autopsy.casemodule.Bundle"/> <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/Case/org-sleuthkit-autopsy-casemodule-RecentCases.instance"/>
</file> </file>
</folder> </folder>
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow"> <file name="org-sleuthkit-autopsy-casemodule-CaseCloseAct.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"/>
<attr name="position" intvalue="103"/> <attr name="position" intvalue="103"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorBefore.instance"> <file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorBefore.instance">
@ -170,7 +171,7 @@
<attr name="position" intvalue="200"/> <attr name="position" intvalue="200"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-AddImageAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-AddImageAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-AddImageAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-AddImageAction.instance"/>
<attr name="position" intvalue="201"/> <attr name="position" intvalue="201"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorAfter.instance"> <file name="org-sleuthkit-autopsy-casemodule-AddImage-separatorAfter.instance">
@ -182,7 +183,7 @@
<attr name="position" intvalue="300"/> <attr name="position" intvalue="300"/>
</file> </file>
<file name="org-sleuthkit-autopsy-casemodule-CasePropertiesAction.shadow"> <file name="org-sleuthkit-autopsy-casemodule-CasePropertiesAction.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CasePropertiesAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CasePropertiesAction.instance"/>
<attr name="position" intvalue="301"/> <attr name="position" intvalue="301"/>
</file> </file>
<file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden"/> <file name="org-netbeans-modules-print-action-PageSetupAction.shadow_hidden"/>
@ -361,7 +362,8 @@
<file name="Clipboard_hidden"/> <file name="Clipboard_hidden"/>
<file name="Memory_hidden"/> <file name="Memory_hidden"/>
<file name="UndoRedo_hidden"/> <file name="UndoRedo_hidden"/>
<folder name="File"> <file name="File_hidden"/>
<folder name="Case">
<file name="org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance"> <file name="org-sleuthkit-autopsy-casemodule-CaseCloseAction.instance">
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseCloseAction"/> <attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseCloseAction"/>
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseCloseAct"/> <attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseCloseAct"/>
@ -385,11 +387,11 @@
<file name="org-sleuthkit-autopsy-report-ReportWizardAction.shadow"> <file name="org-sleuthkit-autopsy-report-ReportWizardAction.shadow">
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.report.Bundle#Toolbars/Reports/org-sleuthkit-autopsy-report-ReportWizardAction.shadow"/> <attr name="displayName" bundlevalue="org.sleuthkit.autopsy.report.Bundle#Toolbars/Reports/org-sleuthkit-autopsy-report-ReportWizardAction.shadow"/>
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-report-ReportWizardAction.instance"/> <attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-report-ReportWizardAction.instance"/>
<attr name="position" intvalue="102"/> <attr name="position" intvalue="103"/>
</file> </file>
</folder> </folder>
<folder name="Ingest"> <folder name="Ingest">
<attr intvalue="103" name="position"/> <attr intvalue="104" name="position"/>
<file name="org-sleuthkit-autopsy-ingest-IngestMessagesAction.shadow"> <file name="org-sleuthkit-autopsy-ingest-IngestMessagesAction.shadow">
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-ingest-IngestMessagesAction.instance"/> <attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-ingest-IngestMessagesAction.instance"/>
</file> </file>
@ -404,10 +406,10 @@
====================================================== --> ====================================================== -->
<folder name="Shortcuts"> <folder name="Shortcuts">
<file name="D-N.shadow"> <file name="D-N.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseNewAction.instance"/>
</file> </file>
<file name="D-O.shadow"> <file name="D-O.shadow">
<attr name="originalFile" stringvalue="Actions/File/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/> <attr name="originalFile" stringvalue="Actions/Case/org-sleuthkit-autopsy-casemodule-CaseOpenAction.instance"/>
</file> </file>
</folder> </folder>

View File

@ -3,7 +3,7 @@
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> <Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties> <Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 5]"/> <Dimension value="[0, 5]"/>
</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="[5, 5]"/> <Dimension value="[5, 5]"/>
@ -56,6 +56,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/corecomponents/Bundle.properties" key="DataResultPanel.directoryTablePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="DataResultPanel.directoryTablePath.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[5, 14]"/>
</Property>
</Properties> </Properties>
</Component> </Component>
<Component class="javax.swing.JLabel" name="numberMatchLabel"> <Component class="javax.swing.JLabel" name="numberMatchLabel">
@ -73,6 +76,11 @@
</Properties> </Properties>
</Component> </Component>
<Container class="javax.swing.JTabbedPane" name="dataResultTabbedPanel"> <Container class="javax.swing.JTabbedPane" name="dataResultTabbedPanel">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[0, 5]"/>
</Property>
</Properties>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/> <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
</Container> </Container>

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013 Basis Technology Corp. * Copyright 2011-2016 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");
@ -56,6 +56,8 @@ import org.sleuthkit.autopsy.coreutils.Logger;
public class DataResultPanel extends javax.swing.JPanel implements DataResult, ChangeListener { public class DataResultPanel extends javax.swing.JPanel implements DataResult, ChangeListener {
private ExplorerManager explorerManager; private ExplorerManager explorerManager;
private ExplorerManagerNodeSelectionListener emNodeSelectionListener;
private Node rootNode; private Node rootNode;
private PropertyChangeSupport pcs; private PropertyChangeSupport pcs;
@ -232,7 +234,8 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
// can push the selections both to its child DataResultViewers and to a DataContent object. // can push the selections both to its child DataResultViewers and to a DataContent object.
// The default DataContent object is a DataContentTopComponent in the data content mode (area), // The default DataContent object is a DataContentTopComponent in the data content mode (area),
// and is the parent of a DataContentPanel that hosts a set of DataContentViewers. // and is the parent of a DataContentPanel that hosts a set of DataContentViewers.
explorerManager.addPropertyChangeListener(new ExplorerManagerNodeSelectionListener()); emNodeSelectionListener = new ExplorerManagerNodeSelectionListener();
explorerManager.addPropertyChangeListener(emNodeSelectionListener);
} }
// Add all the DataContentViewer to the tabbed pannel. // Add all the DataContentViewer to the tabbed pannel.
@ -336,6 +339,11 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
pcs.removePropertyChangeListener(pcl[i]); pcs.removePropertyChangeListener(pcl[i]);
} }
if (null != explorerManager && null != emNodeSelectionListener) {
explorerManager.removePropertyChangeListener(emNodeSelectionListener);
explorerManager = null;
}
// clear all set nodes // clear all set nodes
for (UpdateWrapper drv : this.viewers) { for (UpdateWrapper drv : this.viewers) {
drv.setNode(null); drv.setNode(null);
@ -536,26 +544,29 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
matchLabel = new javax.swing.JLabel(); matchLabel = new javax.swing.JLabel();
dataResultTabbedPanel = new javax.swing.JTabbedPane(); dataResultTabbedPanel = new javax.swing.JTabbedPane();
setMinimumSize(new java.awt.Dimension(5, 5)); setMinimumSize(new java.awt.Dimension(0, 5));
setPreferredSize(new java.awt.Dimension(5, 5)); setPreferredSize(new java.awt.Dimension(5, 5));
org.openide.awt.Mnemonics.setLocalizedText(directoryTablePath, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.directoryTablePath.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(directoryTablePath, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.directoryTablePath.text")); // NOI18N
directoryTablePath.setMinimumSize(new java.awt.Dimension(5, 14));
org.openide.awt.Mnemonics.setLocalizedText(numberMatchLabel, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.numberMatchLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(numberMatchLabel, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.numberMatchLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(matchLabel, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.matchLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(matchLabel, org.openide.util.NbBundle.getMessage(DataResultPanel.class, "DataResultPanel.matchLabel.text")); // NOI18N
dataResultTabbedPanel.setMinimumSize(new java.awt.Dimension(0, 5));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout); this.setLayout(layout);
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(directoryTablePath) .addComponent(directoryTablePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 518, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(numberMatchLabel) .addComponent(numberMatchLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(matchLabel)) .addComponent(matchLabel))
.addComponent(dataResultTabbedPanel) .addComponent(dataResultTabbedPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -564,9 +575,9 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(numberMatchLabel) .addComponent(numberMatchLabel)
.addComponent(matchLabel)) .addComponent(matchLabel))
.addComponent(directoryTablePath)) .addComponent(directoryTablePath, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(0, 0, 0) .addGap(0, 0, 0)
.addComponent(dataResultTabbedPanel, javax.swing.GroupLayout.DEFAULT_SIZE, 340, Short.MAX_VALUE)) .addComponent(dataResultTabbedPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables

View File

@ -1,4 +1,4 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012-16 Basis Technology Corp. * Copyright 2012-16 Basis Technology Corp.
@ -31,6 +31,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -89,7 +90,7 @@ public class ImageUtils {
private static final List<String> GIF_EXTENSION_LIST = Arrays.asList("gif"); private static final List<String> GIF_EXTENSION_LIST = Arrays.asList("gif");
private static final SortedSet<String> GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{"image/gif"}); private static final SortedSet<String> GIF_MIME_SET = ImmutableSortedSet.copyOf(new String[]{"image/gif"});
private static final List<String> SUPPORTED_IMAGE_EXTENSIONS; private static final List<String> SUPPORTED_IMAGE_EXTENSIONS = new ArrayList<>();
private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES; private static final SortedSet<String> SUPPORTED_IMAGE_MIME_TYPES;
private static final boolean openCVLoaded; private static final boolean openCVLoaded;
@ -124,7 +125,8 @@ public class ImageUtils {
} }
openCVLoaded = openCVLoadedTemp; openCVLoaded = openCVLoadedTemp;
SUPPORTED_IMAGE_EXTENSIONS = Arrays.asList(ImageIO.getReaderFileSuffixes()); SUPPORTED_IMAGE_EXTENSIONS.addAll(Arrays.asList(ImageIO.getReaderFileSuffixes()));
SUPPORTED_IMAGE_EXTENSIONS.add("tec"); // Add JFIF .tec files
SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes())); SUPPORTED_IMAGE_MIME_TYPES = new TreeSet<>(Arrays.asList(ImageIO.getReaderMIMETypes()));
/* /*
* special cases and variants that we support, but don't get registered * special cases and variants that we support, but don't get registered
@ -376,6 +378,45 @@ public class ImageUtils {
} }
} }
/**
* Find the offset for the first Start Of Image marker (0xFFD8) in JFIF,
* allowing for leading End Of Image markers.
*
* @param file the AbstractFile to parse
*
* @return Offset of first Start Of Image marker, or 0 if none found. This
* will let ImageIO try to open it from offset 0.
*/
private static long getJfifStartOfImageOffset(AbstractFile file) {
byte[] fileHeaderBuffer;
long length;
try {
length = file.getSize();
if (length % 2 != 0) {
length -= 1; // Make it an even number so we can parse two bytes at a time
}
if (length >= 1024) {
length = 1024;
}
fileHeaderBuffer = readHeader(file, (int) length); // read up to first 1024 bytes
} catch (TskCoreException ex) {
// Couldn't read header. Let ImageIO try it.
return 0;
}
if (fileHeaderBuffer != null) {
for (int index = 0; index < length; index += 2) {
// Look for Start Of Image marker and return the index when it's found
if ((fileHeaderBuffer[index] == (byte) 0xFF) && (fileHeaderBuffer[index + 1] == (byte) 0xD8)) {
return index;
}
}
}
// Didn't match JFIF. Let ImageIO try to open it from offset 0.
return 0;
}
/** /**
* Check if the given file is a png based on header. * Check if the given file is a png based on header.
* *
@ -711,7 +752,7 @@ public class ImageUtils {
*/ */
static private abstract class ReadImageTaskBase extends Task<javafx.scene.image.Image> implements IIOReadProgressListener { static private abstract class ReadImageTaskBase extends Task<javafx.scene.image.Image> implements IIOReadProgressListener {
private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NON-NLS private static final String IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT = "ImageIO could not read {0}. It may be unsupported or corrupt"; //NON-NLS
final AbstractFile file; final AbstractFile file;
// private ImageReader reader; // private ImageReader reader;
@ -726,8 +767,17 @@ public class ImageUtils {
if (image.isError() == false) { if (image.isError() == false) {
return image; return image;
} }
//fall through to default image reading code if there was an error } else if (file.getNameExtension().equalsIgnoreCase("tec")) { //NON-NLS
ReadContentInputStream readContentInputStream = new ReadContentInputStream(file);
// Find first Start Of Image marker
readContentInputStream.seek(getJfifStartOfImageOffset(file));
//use JavaFX to directly read .tec files
javafx.scene.image.Image image = new javafx.scene.image.Image(new BufferedInputStream(readContentInputStream));
if (image.isError() == false) {
return image;
}
} }
//fall through to default image reading code if there was an error
if (isCancelled()) { if (isCancelled()) {
return null; return null;
} }
@ -747,7 +797,7 @@ public class ImageUtils {
try { try {
bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object bufferedImage = imageReader.read(0, param); //should always be same bufferedImage object
} catch (IOException iOException) { } catch (IOException iOException) {
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + iOException.toString(), ImageUtils.getContentPathSafe(file)); //NON-NLS
} finally { } finally {
imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this); imageReader.removeIIOReadProgressListener(ReadImageTaskBase.this);
} }
@ -755,7 +805,8 @@ public class ImageUtils {
return null; return null;
} }
return SwingFXUtils.toFXImage(bufferedImage, null); return SwingFXUtils.toFXImage(bufferedImage, null);
}); }
);
} }
@Override @Override
@ -775,12 +826,10 @@ public class ImageUtils {
try { try {
javafx.scene.image.Image fxImage = get(); javafx.scene.image.Image fxImage = get();
if (fxImage == null) { if (fxImage == null) {
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT, ImageUtils.getContentPathSafe(file)); LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT, ImageUtils.getContentPathSafe(file));
} else { } else if (fxImage.isError()) {
if (fxImage.isError()) { //if there was somekind of error, log it
//if there was somekind of error, log it LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + ObjectUtils.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file));
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + ObjectUtils.toString(fxImage.getException()), ImageUtils.getContentPathSafe(file));
}
} }
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
failed(); failed();
@ -790,7 +839,7 @@ public class ImageUtils {
@Override @Override
protected void failed() { protected void failed() {
super.failed(); super.failed();
LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTE_OR_CORRUPT + ": " + ObjectUtils.toString(getException()), ImageUtils.getContentPathSafe(file)); LOGGER.log(Level.WARNING, IMAGEIO_COULD_NOT_READ_UNSUPPORTED_OR_CORRUPT + ": " + ObjectUtils.toString(getException()), ImageUtils.getContentPathSafe(file));
} }
@Override @Override

View File

@ -57,4 +57,26 @@ public class TextUtil {
return orientation; return orientation;
} }
/**
* This method determines if a passed-in Java char (16 bits) is a valid
* UTF-8 printable character, returning true if so, false if not.
*
* Note that this method can have ramifications for characters outside the
* Unicode Base Multilingual Plane (BMP), which require more than 16 bits.
* We are using Java characters (16 bits) to look at the data and this will
* not accurately identify any non-BMP character (larger than 16 bits)
* ending with 0xFFFF and 0xFFFE. In the interest of a fast solution, we
* have chosen to ignore the extended planes above Unicode BMP for the time
* being. The net result of this is some non-BMP characters may be
* interspersed with '^' characters in Autopsy.
*
* @param ch the character to test
*
* @return Returns true if the character is valid UTF-8, false if not.
*/
public static boolean isValidSolrUTF8(char ch) {
return ((ch <= 0xFDD0 || ch >= 0xFDEF) && (ch > 0x1F || ch == 0x9 || ch == 0xA || ch == 0xD) && (ch != 0xFFFF) && (ch != 0xFFFE));
}
} }

View File

@ -268,7 +268,7 @@ public abstract class AbstractAbstractFileNode<T extends AbstractFile> extends A
map.put(AbstractFilePropertyType.USER_ID.toString(), content.getUid()); map.put(AbstractFilePropertyType.USER_ID.toString(), content.getUid());
map.put(AbstractFilePropertyType.GROUP_ID.toString(), content.getGid()); map.put(AbstractFilePropertyType.GROUP_ID.toString(), content.getGid());
map.put(AbstractFilePropertyType.META_ADDR.toString(), content.getMetaAddr()); map.put(AbstractFilePropertyType.META_ADDR.toString(), content.getMetaAddr());
map.put(AbstractFilePropertyType.ATTR_ADDR.toString(), Long.toString(content.getAttrType().getValue()) + "-" + Long.toString(content.getAttrId())); map.put(AbstractFilePropertyType.ATTR_ADDR.toString(), Long.toString(content.getAttrType().getValue()) + "-" + content.getAttributeId());
map.put(AbstractFilePropertyType.TYPE_DIR.toString(), content.getDirType().getLabel()); map.put(AbstractFilePropertyType.TYPE_DIR.toString(), content.getDirType().getLabel());
map.put(AbstractFilePropertyType.TYPE_META.toString(), content.getMetaType().toString()); map.put(AbstractFilePropertyType.TYPE_META.toString(), content.getMetaType().toString());
map.put(AbstractFilePropertyType.KNOWN.toString(), content.getKnown().getName()); map.put(AbstractFilePropertyType.KNOWN.toString(), content.getKnown().getName());

View File

@ -20,13 +20,13 @@ package org.sleuthkit.autopsy.datamodel;
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 javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.Children; import org.openide.nodes.Children;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.Lookups; import org.openide.util.lookup.Lookups;
import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction; import org.sleuthkit.autopsy.actions.DeleteBlackboardArtifactTagAction;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.BlackboardArtifactTag; import org.sleuthkit.datamodel.BlackboardArtifactTag;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
@ -93,7 +93,11 @@ public class BlackboardArtifactTagNode extends DisplayableItemNode {
@Override @Override
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actions = DataModelActionsFactory.getActions(tag.getContent(), true); List<Action> actions = DataModelActionsFactory.getActions(tag.getContent(), true);
actions.add(null); // Adds a menu item separator. for (Action a : super.getActions(true)) {
actions.add(a);
}
actions.add(null); // Adds a menu item separator.
actions.add(DeleteBlackboardArtifactTagAction.getInstance()); actions.add(DeleteBlackboardArtifactTagAction.getInstance());
return actions.toArray(new Action[0]); return actions.toArray(new Action[0]);
} }

View File

@ -147,7 +147,6 @@ HashsetHits.createSheet.name.name=Name
HashsetHits.createSheet.name.displayName=Name HashsetHits.createSheet.name.displayName=Name
HashsetHits.createSheet.name.desc=no description HashsetHits.createSheet.name.desc=no description
ImageNode.getActions.viewInNewWin.text=View in New Window ImageNode.getActions.viewInNewWin.text=View in New Window
ImageNode.getActions.openFileSearchByAttr.text=Open File Search by Attributes
ImageNode.createSheet.name.name=Name ImageNode.createSheet.name.name=Name
ImageNode.createSheet.name.displayName=Name ImageNode.createSheet.name.displayName=Name
ImageNode.createSheet.name.desc=no description ImageNode.createSheet.name.desc=no description

View File

@ -107,6 +107,9 @@ class ContentTagNode extends DisplayableItemNode {
@Override @Override
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actions = DataModelActionsFactory.getActions(tag.getContent(), false); List<Action> actions = DataModelActionsFactory.getActions(tag.getContent(), false);
for (Action a : super.getActions(true)) {
actions.add(a);
}
actions.add(null); // Adds a menu item separator. actions.add(null); // Adds a menu item separator.
actions.add(DeleteContentTagAction.getInstance()); actions.add(DeleteContentTagAction.getInstance());
return actions.toArray(new Action[0]); return actions.toArray(new Action[0]);

View File

@ -21,10 +21,9 @@ package org.sleuthkit.autopsy.datamodel;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.swing.Action; import javax.swing.Action;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction;
@ -72,6 +71,9 @@ public class DirectoryNode extends AbstractFsContentNode<AbstractFile> {
@Override @Override
public Action[] getActions(boolean popup) { public Action[] getActions(boolean popup) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
for (Action a : super.getActions(true)) {
actions.add(a);
}
if (!getDirectoryBrowseMode()) { if (!getDirectoryBrowseMode()) {
actions.add(new ViewContextAction( actions.add(new ViewContextAction(
NbBundle.getMessage(this.getClass(), "DirectoryNode.getActions.viewFileInDir.text"), this)); NbBundle.getMessage(this.getClass(), "DirectoryNode.getActions.viewFileInDir.text"), this));

View File

@ -79,18 +79,21 @@ public class FileNode extends AbstractFsContentNode<AbstractFile> {
@Override @Override
public Action[] getActions(boolean popup) { public Action[] getActions(boolean popup) {
List<Action> actionsList = new ArrayList<>(); List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
if (!this.getDirectoryBrowseMode()) { if (!this.getDirectoryBrowseMode()) {
actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "FileNode.viewFileInDir.text"), this)); actionsList.add(new ViewContextAction(NbBundle.getMessage(FileNode.class, "FileNode.viewFileInDir.text"), this));
actionsList.add(null); // creates a menu separator actionsList.add(null); // creates a menu separator
} }
actionsList.add(new NewWindowViewAction( actionsList.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "FileNode.getActions.viewInNewWin.text"), this)); NbBundle.getMessage(FileNode.class, "FileNode.getActions.viewInNewWin.text"), this));
actionsList.add(new ExternalViewerAction( actionsList.add(new ExternalViewerAction(
NbBundle.getMessage(this.getClass(), "FileNode.getActions.openInExtViewer.text"), this)); NbBundle.getMessage(FileNode.class, "FileNode.getActions.openInExtViewer.text"), this));
actionsList.add(null); // creates a menu separator actionsList.add(null); // creates a menu separator
actionsList.add(ExtractAction.getInstance()); actionsList.add(ExtractAction.getInstance());
actionsList.add(new HashSearchAction( actionsList.add(new HashSearchAction(
NbBundle.getMessage(this.getClass(), "FileNode.getActions.searchFilesSameMD5.text"), this)); NbBundle.getMessage(FileNode.class, "FileNode.getActions.searchFilesSameMD5.text"), this));
actionsList.add(null); // creates a menu separator actionsList.add(null); // creates a menu separator
actionsList.add(AddContentTagAction.getInstance()); actionsList.add(AddContentTagAction.getInstance());
actionsList.addAll(ContextMenuExtensionPoint.getActions()); actionsList.addAll(ContextMenuExtensionPoint.getActions());

View File

@ -27,7 +27,7 @@ import java.util.List;
*/ */
public class FileTypeExtensions { public class FileTypeExtensions {
private final static List<String> IMAGE_EXTENSIONS = Arrays.asList(".jpg", ".jpeg", ".png", ".psd", ".nef", ".tiff", ".bmp"); //NON-NLS private final static List<String> IMAGE_EXTENSIONS = Arrays.asList(".jpg", ".jpeg", ".png", ".psd", ".nef", ".tiff", ".bmp", ".tec"); //NON-NLS
private final static List<String> VIDEO_EXTENSIONS = Arrays.asList(".aaf", ".3gp", ".asf", ".avi", ".m1v", ".m2v", //NON-NLS private final static List<String> VIDEO_EXTENSIONS = Arrays.asList(".aaf", ".3gp", ".asf", ".avi", ".m1v", ".m2v", //NON-NLS
".m4v", ".mp4", ".mov", ".mpeg", ".mpg", ".mpe", ".mp4", ".rm", ".wmv", ".mpv", ".flv", ".swf"); //NON-NLS ".m4v", ".mp4", ".mov", ".mpeg", ".mpg", ".mpe", ".mp4", ".rm", ".wmv", ".mpv", ".flv", ".swf"); //NON-NLS
private final static List<String> AUDIO_EXTENSIONS = Arrays.asList(".aiff", ".aif", ".flac", ".wav", ".m4a", ".ape", //NON-NLS private final static List<String> AUDIO_EXTENSIONS = Arrays.asList(".aiff", ".aif", ".flac", ".wav", ".m4a", ".ape", //NON-NLS

View File

@ -18,15 +18,28 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import java.awt.event.ActionEvent;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor; import org.sleuthkit.autopsy.directorytree.ExplorerNodeActionVisitor;
import org.sleuthkit.autopsy.directorytree.FileSearchAction; import org.sleuthkit.autopsy.directorytree.FileSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.SleuthkitCase.CaseDbQuery;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* This class is used to represent the "Node" for the image. The children of * This class is used to represent the "Node" for the image. The children of
@ -34,6 +47,8 @@ import org.sleuthkit.datamodel.Image;
*/ */
public class ImageNode extends AbstractContentNode<Image> { public class ImageNode extends AbstractContentNode<Image> {
private static final Logger logger = Logger.getLogger(ImageNode.class.getName());
/** /**
* Helper so that the display name and the name used in building the path * Helper so that the display name and the name used in building the path
* are determined the same way. * are determined the same way.
@ -66,19 +81,53 @@ public class ImageNode extends AbstractContentNode<Image> {
* @return * @return
*/ */
@Override @Override
@Messages({"ImageNode.action.runIngestMods.text=Run Ingest Modules",
"ImageNode.getActions.openFileSearchByAttr.text=Open File Search by Attributes",})
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actionsList = new ArrayList<Action>(); List<Action> actionsList = new ArrayList<Action>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
actionsList.addAll(ExplorerNodeActionVisitor.getActions(content));
actionsList.add(new FileSearchAction(
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
actionsList.add(new AbstractAction(
Bundle.ImageNode_action_runIngestMods_text()) {
@Override
public void actionPerformed(ActionEvent e) {
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
ingestDialog.display();
}
});
actionsList.add(new NewWindowViewAction( actionsList.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "ImageNode.getActions.viewInNewWin.text"), this)); NbBundle.getMessage(this.getClass(), "ImageNode.getActions.viewInNewWin.text"), this));
actionsList.add(new FileSearchAction(
NbBundle.getMessage(this.getClass(), "ImageNode.getActions.openFileSearchByAttr.text")));
actionsList.addAll(ExplorerNodeActionVisitor.getActions(content));
return actionsList.toArray(new Action[0]); return actionsList.toArray(new Action[0]);
} }
@Override @Override
@Messages({"ImageNode.createSheet.size.name=Size (Bytes)",
"ImageNode.createSheet.size.displayName=Size (Bytes)",
"ImageNode.createSheet.size.desc=Size of the data source in bytes.",
"ImageNode.createSheet.type.name=Type",
"ImageNode.createSheet.type.displayName=Type",
"ImageNode.createSheet.type.desc=Type of the image.",
"ImageNode.createSheet.type.text=Image",
"ImageNode.createSheet.sectorSize.name=Sector Size (Bytes)",
"ImageNode.createSheet.sectorSize.displayName=Sector Size (Bytes)",
"ImageNode.createSheet.sectorSize.desc=Sector size of the image in bytes.",
"ImageNode.createSheet.md5.name=MD5 Hash",
"ImageNode.createSheet.md5.displayName=MD5 Hash",
"ImageNode.createSheet.md5.desc=MD5 Hash of the image",
"ImageNode.createSheet.timezone.name=Timezone",
"ImageNode.createSheet.timezone.displayName=Timezone",
"ImageNode.createSheet.timezone.desc=Timezone of the image",
"ImageNode.createSheet.deviceId.name=Device ID",
"ImageNode.createSheet.deviceId.displayName=Device ID",
"ImageNode.createSheet.deviceId.desc=Device ID of the image"})
protected Sheet createSheet() { protected Sheet createSheet() {
Sheet s = super.createSheet(); Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES); Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -92,6 +141,42 @@ public class ImageNode extends AbstractContentNode<Image> {
NbBundle.getMessage(this.getClass(), "ImageNode.createSheet.name.desc"), NbBundle.getMessage(this.getClass(), "ImageNode.createSheet.name.desc"),
getDisplayName())); getDisplayName()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_type_name(),
Bundle.ImageNode_createSheet_type_displayName(),
Bundle.ImageNode_createSheet_type_desc(),
Bundle.ImageNode_createSheet_type_text()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_size_name(),
Bundle.ImageNode_createSheet_size_displayName(),
Bundle.ImageNode_createSheet_size_desc(),
this.content.getSize()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_sectorSize_name(),
Bundle.ImageNode_createSheet_sectorSize_displayName(),
Bundle.ImageNode_createSheet_sectorSize_desc(),
this.content.getSsize()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_md5_name(),
Bundle.ImageNode_createSheet_md5_displayName(),
Bundle.ImageNode_createSheet_md5_desc(),
this.content.getMd5()));
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_timezone_name(),
Bundle.ImageNode_createSheet_timezone_displayName(),
Bundle.ImageNode_createSheet_timezone_desc(),
this.content.getTimeZone()));
try (CaseDbQuery query = Case.getCurrentCase().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) {
ResultSet deviceIdSet = query.getResultSet();
if (deviceIdSet.next()) {
ss.put(new NodeProperty<>(Bundle.ImageNode_createSheet_deviceId_name(),
Bundle.ImageNode_createSheet_deviceId_displayName(),
Bundle.ImageNode_createSheet_deviceId_desc(),
deviceIdSet.getString("device_id")));
}
} catch (SQLException | TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get device id for the following image: " + this.content.getId(), ex);
}
return s; return s;
} }

View File

@ -25,11 +25,11 @@ import java.util.Map;
import javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
@ -116,6 +116,9 @@ public class LayoutFileNode extends AbstractAbstractFileNode<LayoutFile> {
@Override @Override
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actionsList = new ArrayList<>(); List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
actionsList.add(new NewWindowViewAction( actionsList.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "LayoutFileNode.getActions.viewInNewWin.text"), this)); NbBundle.getMessage(this.getClass(), "LayoutFileNode.getActions.viewInNewWin.text"), this));
actionsList.add(new ExternalViewerAction( actionsList.add(new ExternalViewerAction(

View File

@ -25,12 +25,12 @@ import java.util.Map;
import javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.directorytree.ExternalViewerAction; import org.sleuthkit.autopsy.directorytree.ExternalViewerAction;
import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.HashSearchAction; import org.sleuthkit.autopsy.directorytree.HashSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.directorytree.ViewContextAction; import org.sleuthkit.autopsy.directorytree.ViewContextAction;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -82,6 +82,9 @@ public class LocalFileNode extends AbstractAbstractFileNode<AbstractFile> {
@Override @Override
public Action[] getActions(boolean context) { public Action[] getActions(boolean context) {
List<Action> actionsList = new ArrayList<>(); List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "LocalFileNode.viewFileInDir.text"), this.content)); actionsList.add(new ViewContextAction(NbBundle.getMessage(this.getClass(), "LocalFileNode.viewFileInDir.text"), this.content));
actionsList.add(null); // creates a menu separator actionsList.add(null); // creates a menu separator
actionsList.add(new NewWindowViewAction( actionsList.add(new NewWindowViewAction(

View File

@ -18,19 +18,32 @@
*/ */
package org.sleuthkit.autopsy.datamodel; package org.sleuthkit.autopsy.datamodel;
import java.awt.event.ActionEvent;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import org.openide.nodes.Sheet; import org.openide.nodes.Sheet;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.directorytree.ExtractAction; import org.sleuthkit.autopsy.directorytree.ExtractAction;
import org.sleuthkit.autopsy.directorytree.FileSearchAction;
import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.directorytree.NewWindowViewAction;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.autopsy.ingest.RunIngestModulesDialog;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.VirtualDirectory;
/** /**
* Node for layout dir * Node for layout dir
@ -73,18 +86,46 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
* @return * @return
*/ */
@Override @Override
@NbBundle.Messages({"VirtualDirectoryNode.action.runIngestMods.text=Run Ingest Modules"})
public Action[] getActions(boolean popup) { public Action[] getActions(boolean popup) {
List<Action> actions = new ArrayList<>(); List<Action> actions = new ArrayList<>();
for (Action a : super.getActions(true)) {
actions.add(a);
}
actions.add(new NewWindowViewAction( actions.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.getActions.viewInNewWin.text"), this)); NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.getActions.viewInNewWin.text"), this));
actions.add(null); // creates a menu separator actions.add(null); // creates a menu separator
actions.add(ExtractAction.getInstance()); actions.add(ExtractAction.getInstance());
actions.add(null); // creates a menu separator actions.add(null); // creates a menu separator
actions.add(new FileSearchAction(
Bundle.ImageNode_getActions_openFileSearchByAttr_text()));
actions.add(new AbstractAction(
Bundle.VirtualDirectoryNode_action_runIngestMods_text()) {
@Override
public void actionPerformed(ActionEvent e) {
final RunIngestModulesDialog ingestDialog = new RunIngestModulesDialog(Collections.<Content>singletonList(content));
ingestDialog.display();
}
});
actions.addAll(ContextMenuExtensionPoint.getActions()); actions.addAll(ContextMenuExtensionPoint.getActions());
return actions.toArray(new Action[0]); return actions.toArray(new Action[0]);
} }
@Override @Override
@Messages({"VirtualDirectoryNode.createSheet.size.name=Size (Bytes)",
"VirtualDirectoryNode.createSheet.size.displayName=Size (Bytes)",
"VirtualDirectoryNode.createSheet.size.desc=Size of the data source in bytes.",
"VirtualDirectoryNode.createSheet.type.name=Type",
"VirtualDirectoryNode.createSheet.type.displayName=Type",
"VirtualDirectoryNode.createSheet.type.desc=Type of the image.",
"VirtualDirectoryNode.createSheet.type.text=Logical File Set",
"VirtualDirectoryNode.createSheet.timezone.name=Timezone",
"VirtualDirectoryNode.createSheet.timezone.displayName=Timezone",
"VirtualDirectoryNode.createSheet.timezone.desc=Timezone of the image",
"VirtualDirectoryNode.createSheet.deviceId.name=Device ID",
"VirtualDirectoryNode.createSheet.deviceId.displayName=Device ID",
"VirtualDirectoryNode.createSheet.deviceId.desc=Device ID of the image"})
protected Sheet createSheet() { protected Sheet createSheet() {
Sheet s = super.createSheet(); Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES); Sheet.Set ss = s.get(Sheet.PROPERTIES);
@ -93,18 +134,52 @@ public class VirtualDirectoryNode extends AbstractAbstractFileNode<VirtualDirect
s.put(ss); s.put(ss);
} }
Map<String, Object> map = new LinkedHashMap<>();
fillPropertyMap(map, content);
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.name"), ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), NbBundle.getMessage(this.getClass(),
"VirtualDirectoryNode.createSheet.name.displayName"), "VirtualDirectoryNode.createSheet.name.displayName"),
NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.desc"), NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.name.desc"),
getName())); getName()));
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.noDesc"); if (!this.content.isDataSource()) {
for (Map.Entry<String, Object> entry : map.entrySet()) { Map<String, Object> map = new LinkedHashMap<>();
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue())); fillPropertyMap(map, content);
final String NO_DESCR = NbBundle.getMessage(this.getClass(), "VirtualDirectoryNode.createSheet.noDesc");
for (Map.Entry<String, Object> entry : map.entrySet()) {
ss.put(new NodeProperty<>(entry.getKey(), entry.getKey(), NO_DESCR, entry.getValue()));
}
} else {
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_type_name(),
Bundle.VirtualDirectoryNode_createSheet_type_displayName(),
Bundle.VirtualDirectoryNode_createSheet_type_desc(),
Bundle.VirtualDirectoryNode_createSheet_type_text()));
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_size_name(),
Bundle.VirtualDirectoryNode_createSheet_size_displayName(),
Bundle.VirtualDirectoryNode_createSheet_size_desc(),
this.content.getSize()));
try (SleuthkitCase.CaseDbQuery query = Case.getCurrentCase().getSleuthkitCase().executeQuery("SELECT time_zone FROM data_source_info WHERE obj_id = " + this.content.getId())) {
ResultSet timeZoneSet = query.getResultSet();
if (timeZoneSet.next()) {
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_timezone_name(),
Bundle.VirtualDirectoryNode_createSheet_timezone_displayName(),
Bundle.VirtualDirectoryNode_createSheet_timezone_desc(),
timeZoneSet.getString("time_zone")));
}
} catch (SQLException | TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get time zone for the following image: " + this.content.getId(), ex);
}
try (SleuthkitCase.CaseDbQuery query = Case.getCurrentCase().getSleuthkitCase().executeQuery("SELECT device_id FROM data_source_info WHERE obj_id = " + this.content.getId());) {
ResultSet deviceIdSet = query.getResultSet();
if (deviceIdSet.next()) {
ss.put(new NodeProperty<>(Bundle.VirtualDirectoryNode_createSheet_deviceId_name(),
Bundle.VirtualDirectoryNode_createSheet_deviceId_displayName(),
Bundle.VirtualDirectoryNode_createSheet_deviceId_desc(),
deviceIdSet.getString("device_id")));
}
} catch (SQLException | TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to get device id for the following image: " + this.content.getId(), ex);
}
} }
return s; return s;

View File

@ -131,6 +131,10 @@ public class VolumeNode extends AbstractContentNode<Volume> {
public Action[] getActions(boolean popup) { public Action[] getActions(boolean popup) {
List<Action> actionsList = new ArrayList<>(); List<Action> actionsList = new ArrayList<>();
for (Action a : super.getActions(true)) {
actionsList.add(a);
}
actionsList.add(new NewWindowViewAction( actionsList.add(new NewWindowViewAction(
NbBundle.getMessage(this.getClass(), "VolumeNode.getActions.viewInNewWin.text"), this)); NbBundle.getMessage(this.getClass(), "VolumeNode.getActions.viewInNewWin.text"), this));
actionsList.addAll(ExplorerNodeActionVisitor.getActions(content)); actionsList.addAll(ExplorerNodeActionVisitor.getActions(content));

View File

@ -18,27 +18,14 @@
*/ */
package org.sleuthkit.autopsy.directorytree; package org.sleuthkit.autopsy.directorytree;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.logging.Level;
import javax.swing.AbstractAction; import javax.swing.AbstractAction;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.actions.AddContentTagAction; import org.sleuthkit.autopsy.actions.AddContentTagAction;
import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint; import org.sleuthkit.autopsy.coreutils.ContextMenuExtensionPoint;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.ContentVisitor;
import org.sleuthkit.datamodel.DerivedFile; import org.sleuthkit.datamodel.DerivedFile;
@ -77,8 +64,6 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
@Override @Override
public List<? extends Action> visit(final Image img) { public List<? extends Action> visit(final Image img) {
List<Action> lst = new ArrayList<>(); List<Action> lst = new ArrayList<>();
lst.add(new ImageDetails(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.imgDetails.title"), img));
//TODO lst.add(new ExtractAction("Extract Image", img)); //TODO lst.add(new ExtractAction("Extract Image", img));
lst.add(new ExtractUnallocAction( lst.add(new ExtractUnallocAction(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.extUnallocToSingleFiles"), img)); NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.extUnallocToSingleFiles"), img));
@ -87,15 +72,12 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
@Override @Override
public List<? extends Action> visit(final FileSystem fs) { public List<? extends Action> visit(final FileSystem fs) {
return Collections.singletonList(new FileSystemDetails( return new ArrayList<>();
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.fileSystemDetails.title"), fs));
} }
@Override @Override
public List<? extends Action> visit(final Volume vol) { public List<? extends Action> visit(final Volume vol) {
List<AbstractAction> lst = new ArrayList<>(); List<AbstractAction> lst = new ArrayList<>();
lst.add(new VolumeDetails(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.volumeDetails.title"), vol));
lst.add(new ExtractUnallocAction( lst.add(new ExtractUnallocAction(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.extUnallocToSingleFile"), vol)); NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.action.extUnallocToSingleFile"), vol));
return lst; return lst;
@ -152,242 +134,4 @@ public class ExplorerNodeActionVisitor extends ContentVisitor.Default<List<? ext
return Collections.<Action>emptyList(); return Collections.<Action>emptyList();
} }
//Below here are classes regarding node-specific actions
/**
* VolumeDetails class
*/
private class VolumeDetails extends AbstractAction {
private final String title;
private final Volume vol;
VolumeDetails(String title, Volume vol) {
super(title);
this.title = title;
this.vol = vol;
}
@Override
public void actionPerformed(ActionEvent e) {
final JFrame frame = new JFrame(title);
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
popUpWindow.setSize(800, 400);
int w = popUpWindow.getSize().width;
int h = popUpWindow.getSize().height;
// set the location of the popUp Window on the center of the screen
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
VolumeDetailsPanel volumeDetailPanel = new VolumeDetailsPanel();
Boolean counter = false;
volumeDetailPanel.setVolumeIDValue(Long.toString(vol.getAddr()));
volumeDetailPanel.setStartValue(Long.toString(vol.getStart()));
volumeDetailPanel.setLengthValue(Long.toString(vol.getLength()));
volumeDetailPanel.setDescValue(vol.getDescription());
volumeDetailPanel.setFlagsValue(vol.getFlagsAsString());
counter = true;
if (counter) {
// add the volume detail panel to the popUp window
popUpWindow.add(volumeDetailPanel);
} else {
// error handler if no volume matches
JLabel error = new JLabel(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.volDetail.noVolMatchErr"));
error.setFont(error.getFont().deriveFont(Font.BOLD, 24));
popUpWindow.add(error);
}
// add the command to close the window to the button on the Volume Detail Panel
volumeDetailPanel.setOKButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
popUpWindow.dispose();
}
});
popUpWindow.pack();
popUpWindow.setResizable(false);
popUpWindow.setVisible(true);
}
}
/**
* ImageDetails panel class
*/
private class ImageDetails extends AbstractAction {
final String title;
final Image img;
ImageDetails(String title, Image img) {
super(title);
this.title = title;
this.img = img;
}
@Override
public void actionPerformed(ActionEvent e) {
final JFrame frame = new JFrame(title);
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
// if we select the Image Details menu
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
// set the popUp window / JFrame
popUpWindow.setSize(750, 400);
int w = popUpWindow.getSize().width;
int h = popUpWindow.getSize().height;
// set the location of the popUp Window on the center of the screen
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
ImageDetailsPanel imgDetailPanel = new ImageDetailsPanel();
Boolean counter = false;
imgDetailPanel.setImgNameValue(img.getName());
imgDetailPanel.setImgTypeValue(img.getType().getName());
imgDetailPanel.setImgSectorSizeValue(Long.toString(img.getSsize()));
imgDetailPanel.setImgTotalSizeValue(Long.toString(img.getSize()));
String hash = img.getMd5();
// don't show the hash if there isn't one
imgDetailPanel.setVisibleHashInfo(hash != null);
imgDetailPanel.setImgHashValue(hash);
counter = true;
if (counter) {
// add the volume detail panel to the popUp window
popUpWindow.add(imgDetailPanel);
} else {
// error handler if no volume matches
JLabel error = new JLabel(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.imgDetail.noVolMatchesErr"));
error.setFont(error.getFont().deriveFont(Font.BOLD, 24));
popUpWindow.add(error);
}
// add the command to close the window to the button on the Volume Detail Panel
imgDetailPanel.setOKButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
popUpWindow.dispose();
}
});
popUpWindow.pack();
popUpWindow.setResizable(false);
popUpWindow.setVisible(true);
}
}
/**
* FileSystemDetails class
*/
private class FileSystemDetails extends AbstractAction {
private final FileSystem fs;
private final String title;
FileSystemDetails(String title, FileSystem fs) {
super(title);
this.title = title;
this.fs = fs;
}
@Override
public void actionPerformed(ActionEvent e) {
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
final JFrame frame = new JFrame(title);
final JDialog popUpWindow = new JDialog(frame, title, true); // to make the popUp Window to be modal
// set the popUp window / JFrame
popUpWindow.setSize(1000, 500);
int w = popUpWindow.getSize().width;
int h = popUpWindow.getSize().height;
// set the location of the popUp Window on the center of the screen
popUpWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
String[] columnNames = new String[]{
"fs_id", //NON-NLS
"img_offset", //NON-NLS
"par_id", //NON-NLS
"fs_type", //NON-NLS
"block_size", //NON-NLS
"block_count", //NON-NLS
"root_inum", //NON-NLS
"first_inum", //NON-NLS
"last_inum" //NON-NLS
};
Object[][] rowValues = new Object[1][9];
Content parent = null;
try {
parent = fs.getParent();
} catch (Exception ex) {
throw new RuntimeException(
NbBundle.getMessage(this.getClass(), "ExplorerNodeActionVisitor.exception.probGetParent.text",
FileSystem.class.getName(), fs), ex);
}
long id = -1;
if (parent != null) {
id = parent.getId();
}
Arrays.fill(rowValues, 0, 1, new Object[]{
fs.getId(),
fs.getImageOffset(),
id,
fs.getFsType(),
fs.getBlock_size(),
fs.getBlock_count(),
fs.getRoot_inum(),
fs.getFirst_inum(),
fs.getLastInum()
});
JTable table = new JTable(new DefaultTableModel(rowValues, columnNames));
FileSystemDetailsPanel fsdPanel = new FileSystemDetailsPanel();
// add the command to close the window to the button on the Volume Detail Panel
fsdPanel.setOKButtonActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
popUpWindow.dispose();
}
});
try {
fsdPanel.setFileSystemTypeValue(table.getValueAt(0, 3).toString());
fsdPanel.setImageOffsetValue(table.getValueAt(0, 1).toString());
fsdPanel.setVolumeIDValue(table.getValueAt(0, 2).toString()); //TODO: fix this to parent id, not vol id
fsdPanel.setBlockSizeValue(table.getValueAt(0, 4).toString());
fsdPanel.setBlockCountValue(table.getValueAt(0, 5).toString());
fsdPanel.setRootInumValue(table.getValueAt(0, 6).toString());
fsdPanel.setFirstInumValue(table.getValueAt(0, 7).toString());
fsdPanel.setLastInumValue(table.getValueAt(0, 8).toString());
popUpWindow.add(fsdPanel);
} catch (Exception ex) {
Logger.getLogger(ExplorerNodeActionVisitor.class.getName()).log(Level.WARNING, "Error setting up File System Details panel.", ex); //NON-NLS
}
popUpWindow.pack();
popUpWindow.setResizable(false);
popUpWindow.setVisible(true);
}
}
} }

View File

@ -27,6 +27,7 @@ import java.util.HashSet;
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.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -127,6 +128,7 @@ public final class ExternalResultsImporter {
} }
} }
@Messages({"ExternalResultsImporter.indexError.message=Failed to index imported artifact for keyword search."})
private void importArtifacts(ExternalResults results) { private void importArtifacts(ExternalResults results) {
SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase(); SleuthkitCase caseDb = Case.getCurrentCase().getSleuthkitCase();
for (ExternalResults.Artifact artifactData : results.getArtifacts()) { for (ExternalResults.Artifact artifactData : results.getArtifacts()) {
@ -200,9 +202,9 @@ public final class ExternalResultsImporter {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(artifact); blackboard.indexArtifact(artifact);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", artifact.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), artifact.getDisplayName()); Bundle.ExternalResultsImporter_indexError_message(), artifact.getDisplayName());
} }
if (standardArtifactTypeIds.contains(artifactTypeId)) { if (standardArtifactTypeIds.contains(artifactTypeId)) {

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent; import javax.swing.JComponent;
/** /**
@ -39,4 +40,9 @@ abstract class AbstractFileSearchFilter<T extends JComponent> implements FileSea
public T getComponent() { public T getComponent() {
return this.component; return this.component;
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener listener) {
this.getComponent().addPropertyChangeListener(listener);
}
} }

View File

@ -205,6 +205,11 @@ class DateSearchFilter extends AbstractFileSearchFilter<DateSearchPanel> {
getComponent().addActionListener(l); getComponent().addActionListener(l);
} }
@Override
public boolean isValid() {
return this.getComponent().isValidSearch();
}
/** /**
* Inner class to put the separator inside the combo box. * Inner class to put the separator inside the combo box.
*/ */

View File

@ -236,6 +236,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.modifiedCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.modifiedCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="modifiedCheckBoxActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="changedCheckBox"> <Component class="javax.swing.JCheckBox" name="changedCheckBox">
<Properties> <Properties>
@ -244,6 +247,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.changedCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.changedCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="changedCheckBoxActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="accessedCheckBox"> <Component class="javax.swing.JCheckBox" name="accessedCheckBox">
<Properties> <Properties>
@ -252,6 +258,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.accessedCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.accessedCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="accessedCheckBoxActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="createdCheckBox"> <Component class="javax.swing.JCheckBox" name="createdCheckBox">
<Properties> <Properties>
@ -260,6 +269,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.createdCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="DateSearchPanel.createdCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="createdCheckBoxActionPerformed"/>
</Events>
</Component> </Component>
<Component class="org.jbundle.thin.base.screen.jcalendarbutton.JCalendarButton" name="dateFromButtonCalendar"> <Component class="org.jbundle.thin.base.screen.jcalendarbutton.JCalendarButton" name="dateFromButtonCalendar">
<Properties> <Properties>

View File

@ -20,6 +20,8 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.ParseException; import java.text.ParseException;
import java.util.Date; import java.util.Date;
@ -37,6 +39,7 @@ class DateSearchPanel extends javax.swing.JPanel {
DateFormat dateFormat; DateFormat dateFormat;
List<String> timeZones; List<String> timeZones;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
DateSearchPanel(DateFormat dateFormat, List<String> timeZones) { DateSearchPanel(DateFormat dateFormat, List<String> timeZones) {
this.dateFormat = dateFormat; this.dateFormat = dateFormat;
@ -133,6 +136,16 @@ class DateSearchPanel extends javax.swing.JPanel {
this.changedCheckBox.setEnabled(enable); this.changedCheckBox.setEnabled(enable);
this.createdCheckBox.setEnabled(enable); this.createdCheckBox.setEnabled(enable);
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener pcl) {
pcs.addPropertyChangeListener(pcl);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener pcl) {
pcs.removePropertyChangeListener(pcl);
}
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
@ -209,15 +222,35 @@ class DateSearchPanel extends javax.swing.JPanel {
modifiedCheckBox.setSelected(true); modifiedCheckBox.setSelected(true);
modifiedCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.modifiedCheckBox.text")); // NOI18N modifiedCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.modifiedCheckBox.text")); // NOI18N
modifiedCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
modifiedCheckBoxActionPerformed(evt);
}
});
changedCheckBox.setSelected(true); changedCheckBox.setSelected(true);
changedCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.changedCheckBox.text")); // NOI18N changedCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.changedCheckBox.text")); // NOI18N
changedCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
changedCheckBoxActionPerformed(evt);
}
});
accessedCheckBox.setSelected(true); accessedCheckBox.setSelected(true);
accessedCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.accessedCheckBox.text")); // NOI18N accessedCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.accessedCheckBox.text")); // NOI18N
accessedCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
accessedCheckBoxActionPerformed(evt);
}
});
createdCheckBox.setSelected(true); createdCheckBox.setSelected(true);
createdCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.createdCheckBox.text")); // NOI18N createdCheckBox.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.createdCheckBox.text")); // NOI18N
createdCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
createdCheckBoxActionPerformed(evt);
}
});
dateFromButtonCalendar.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateFromButtonCalendar.text")); // NOI18N dateFromButtonCalendar.setText(org.openide.util.NbBundle.getMessage(DateSearchPanel.class, "DateSearchPanel.dateFromButtonCalendar.text")); // NOI18N
dateFromButtonCalendar.addPropertyChangeListener(new java.beans.PropertyChangeListener() { dateFromButtonCalendar.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
@ -349,8 +382,25 @@ class DateSearchPanel extends javax.swing.JPanel {
private void dateCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateCheckBoxActionPerformed private void dateCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dateCheckBoxActionPerformed
this.setComponentsEnabled(); this.setComponentsEnabled();
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_dateCheckBoxActionPerformed }//GEN-LAST:event_dateCheckBoxActionPerformed
private void modifiedCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_modifiedCheckBoxActionPerformed
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_modifiedCheckBoxActionPerformed
private void accessedCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_accessedCheckBoxActionPerformed
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_accessedCheckBoxActionPerformed
private void createdCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createdCheckBoxActionPerformed
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_createdCheckBoxActionPerformed
private void changedCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_changedCheckBoxActionPerformed
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_changedCheckBoxActionPerformed
/** /**
* Validate and set the datetime field on the screen given a datetime * Validate and set the datetime field on the screen given a datetime
* string. * string.
@ -379,6 +429,13 @@ class DateSearchPanel extends javax.swing.JPanel {
dateToTextField.setText(dateStringResult); dateToTextField.setText(dateStringResult);
dateToButtonCalendar.setTargetDate(date); dateToButtonCalendar.setTargetDate(date);
} }
boolean isValidSearch() {
return this.accessedCheckBox.isSelected() ||
this.changedCheckBox.isSelected() ||
this.createdCheckBox.isSelected() ||
this.modifiedCheckBox.isSelected();
}
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox accessedCheckBox; private javax.swing.JCheckBox accessedCheckBox;
private javax.swing.JCheckBox changedCheckBox; private javax.swing.JCheckBox changedCheckBox;

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import javax.swing.JComponent; import javax.swing.JComponent;
/** /**
@ -40,6 +41,13 @@ interface FileSearchFilter {
*/ */
boolean isEnabled(); boolean isEnabled();
/**
* Checks if the panel has valid input for search.
*
* @return Whether the panel has valid input for search.
*/
boolean isValid();
/** /**
* Gets predicate expression to include in the SQL filter expression * Gets predicate expression to include in the SQL filter expression
* *
@ -56,6 +64,13 @@ interface FileSearchFilter {
*/ */
void addActionListener(ActionListener l); void addActionListener(ActionListener l);
/**
* Adds the property change listener to the panel
*
* @param listener the listener to add.
*/
void addPropertyChangeListener(PropertyChangeListener listener);
/** /**
* Thrown if a filter's inputs are invalid * Thrown if a filter's inputs are invalid
*/ */

View File

@ -17,38 +17,35 @@
* limitations under the License. * limitations under the License.
*/ */
/* /*
* FileSearchPanel.java * FileSearchPanel.java
* *
* Created on Mar 5, 2012, 1:51:50 PM * Created on Mar 5, 2012, 1:51:50 PM
*/ */
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.awt.BorderLayout;
import java.awt.Component; import java.awt.Component;
import java.awt.Cursor; import java.awt.Cursor;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
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 javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JLabel; import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder; import javax.swing.border.EmptyBorder;
import org.openide.DialogDisplayer; import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle;
import org.openide.windows.TopComponent; import org.openide.windows.TopComponent;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent; import org.sleuthkit.autopsy.corecomponents.DataResultTopComponent;
import org.sleuthkit.autopsy.corecomponents.TableFilterNode; import org.sleuthkit.autopsy.corecomponents.TableFilterNode;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException; import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
@ -64,6 +61,10 @@ class FileSearchPanel extends javax.swing.JPanel {
private static int resultWindowCount = 0; //keep track of result windows so they get unique names private static int resultWindowCount = 0; //keep track of result windows so they get unique names
private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text"); private static final String EMPTY_WHERE_CLAUSE = NbBundle.getMessage(DateSearchFilter.class, "FileSearchPanel.emptyWhereClause.text");
enum EVENT {
CHECKED
}
/** /**
* Creates new form FileSearchPanel * Creates new form FileSearchPanel
*/ */
@ -100,25 +101,39 @@ class FileSearchPanel extends javax.swing.JPanel {
filterPanel.add(fa); filterPanel.add(fa);
} }
for (FileSearchFilter filter : this.getFilters()) {
filter.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
searchButton.setEnabled(isValidSearch());
}
});
}
addListenerToAll(new ActionListener() { addListenerToAll(new ActionListener() {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
search(); search();
} }
}); });
searchButton.setEnabled(isValidSearch());
} }
/** /**
* @return true if any of the filters in the panel are enabled (checked) * @return true if any of the filters in the panel are enabled (checked)
*/ */
private boolean anyFiltersEnabled() { private boolean isValidSearch() {
boolean enabled = false;
for (FileSearchFilter filter : this.getFilters()) { for (FileSearchFilter filter : this.getFilters()) {
if (filter.isEnabled()) { if (filter.isEnabled()) {
return true; enabled = true;
if (!filter.isValid()) {
return false;
}
} }
} }
return false; return enabled;
} }
/** /**
@ -129,7 +144,7 @@ class FileSearchPanel extends javax.swing.JPanel {
// change the cursor to "waiting cursor" for this operation // change the cursor to "waiting cursor" for this operation
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
try { try {
if (this.anyFiltersEnabled()) { if (this.isValidSearch()) {
String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount); String title = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.title", ++resultWindowCount);
String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText"); String pathText = NbBundle.getMessage(this.getClass(), "FileSearchPanel.search.results.pathText");
@ -290,6 +305,7 @@ class FileSearchPanel extends javax.swing.JPanel {
.addContainerGap()) .addContainerGap())
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel filterPanel; private javax.swing.JPanel filterPanel;
private javax.swing.JButton searchButton; private javax.swing.JButton searchButton;

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.datamodel.TskData.FileKnown; import org.sleuthkit.datamodel.TskData.FileKnown;
@ -42,6 +41,7 @@ class KnownStatusSearchFilter extends AbstractFileSearchFilter<KnownStatusSearch
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return this.getComponent().getKnownCheckBox().isSelected(); return this.getComponent().getKnownCheckBox().isSelected();
} }
@Override @Override
@ -83,4 +83,9 @@ class KnownStatusSearchFilter extends AbstractFileSearchFilter<KnownStatusSearch
@Override @Override
public void addActionListener(ActionListener l) { public void addActionListener(ActionListener l) {
} }
@Override
public boolean isValid() {
return this.getComponent().isValidSearch();
}
} }

View File

@ -64,6 +64,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="KnownStatusSearchPanel.unknownOptionCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="KnownStatusSearchPanel.unknownOptionCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="unknownOptionCheckBoxActionPerformed"/>
</Events>
</Component> </Component>
<Component class="javax.swing.JCheckBox" name="knownOptionCheckBox"> <Component class="javax.swing.JCheckBox" name="knownOptionCheckBox">
<Properties> <Properties>
@ -83,6 +86,9 @@
<ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="KnownStatusSearchPanel.knownBadOptionCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/filesearch/Bundle.properties" key="KnownStatusSearchPanel.knownBadOptionCheckBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="knownBadOptionCheckBoxActionPerformed"/>
</Events>
</Component> </Component>
</SubComponents> </SubComponents>
</Form> </Form>

View File

@ -17,13 +17,15 @@
* limitations under the License. * limitations under the License.
*/ */
/* /*
* KnownStatusSearchPanel.java * KnownStatusSearchPanel.java
* *
* Created on Oct 19, 2011, 11:45:44 AM * Created on Oct 19, 2011, 11:45:44 AM
*/ */
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
/** /**
@ -32,6 +34,8 @@ import javax.swing.JCheckBox;
*/ */
class KnownStatusSearchPanel extends javax.swing.JPanel { class KnownStatusSearchPanel extends javax.swing.JPanel {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/** /**
* Creates new form KnownStatusSearchPanel * Creates new form KnownStatusSearchPanel
*/ */
@ -55,7 +59,7 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
JCheckBox getUnknownOptionCheckBox() { JCheckBox getUnknownOptionCheckBox() {
return unknownOptionCheckBox; return unknownOptionCheckBox;
} }
private void setComponentsEnabled() { private void setComponentsEnabled() {
boolean enabled = this.knownCheckBox.isSelected(); boolean enabled = this.knownCheckBox.isSelected();
this.unknownOptionCheckBox.setEnabled(enabled); this.unknownOptionCheckBox.setEnabled(enabled);
@ -63,6 +67,20 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
this.knownBadOptionCheckBox.setEnabled(enabled); this.knownBadOptionCheckBox.setEnabled(enabled);
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener pcl) {
pcs.addPropertyChangeListener(pcl);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener pcl) {
pcs.removePropertyChangeListener(pcl);
}
boolean isValidSearch() {
return this.unknownOptionCheckBox.isSelected() || this.knownBadOptionCheckBox.isSelected() || this.knownOptionCheckBox.isSelected();
}
/** /**
* This method is called from within the constructor to initialize the form. * 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 * WARNING: Do NOT modify this code. The content of this method is always
@ -86,6 +104,11 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
unknownOptionCheckBox.setSelected(true); unknownOptionCheckBox.setSelected(true);
unknownOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.unknownOptionCheckBox.text")); // NOI18N unknownOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.unknownOptionCheckBox.text")); // NOI18N
unknownOptionCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
unknownOptionCheckBoxActionPerformed(evt);
}
});
knownOptionCheckBox.setSelected(true); knownOptionCheckBox.setSelected(true);
knownOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.knownOptionCheckBox.text")); // NOI18N knownOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.knownOptionCheckBox.text")); // NOI18N
@ -97,6 +120,11 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
knownBadOptionCheckBox.setSelected(true); knownBadOptionCheckBox.setSelected(true);
knownBadOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.knownBadOptionCheckBox.text")); // NOI18N knownBadOptionCheckBox.setText(org.openide.util.NbBundle.getMessage(KnownStatusSearchPanel.class, "KnownStatusSearchPanel.knownBadOptionCheckBox.text")); // NOI18N
knownBadOptionCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
knownBadOptionCheckBoxActionPerformed(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);
@ -127,13 +155,22 @@ class KnownStatusSearchPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void knownOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownOptionCheckBoxActionPerformed private void knownOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownOptionCheckBoxActionPerformed
// TODO add your handling code here: pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_knownOptionCheckBoxActionPerformed }//GEN-LAST:event_knownOptionCheckBoxActionPerformed
private void knownCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownCheckBoxActionPerformed private void knownCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownCheckBoxActionPerformed
setComponentsEnabled(); setComponentsEnabled();
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_knownCheckBoxActionPerformed }//GEN-LAST:event_knownCheckBoxActionPerformed
private void unknownOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_unknownOptionCheckBoxActionPerformed
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_unknownOptionCheckBoxActionPerformed
private void knownBadOptionCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_knownBadOptionCheckBoxActionPerformed
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_knownBadOptionCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JCheckBox knownBadOptionCheckBox; private javax.swing.JCheckBox knownBadOptionCheckBox;
private javax.swing.JCheckBox knownCheckBox; private javax.swing.JCheckBox knownCheckBox;

View File

@ -10,28 +10,28 @@ import java.awt.event.ActionListener;
/** /**
* Filter by mime type used in filter areas of file search by attribute. * Filter by mime type used in filter areas of file search by attribute.
*/ */
class MimeTypeFilter extends AbstractFileSearchFilter<MimeTypePanel> { class MimeTypeFilter extends AbstractFileSearchFilter<MimeTypePanel> {
public MimeTypeFilter(MimeTypePanel component) { public MimeTypeFilter(MimeTypePanel component) {
super(component); super(component);
} }
public MimeTypeFilter() { public MimeTypeFilter() {
this(new MimeTypePanel()); this(new MimeTypePanel());
} }
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return this.getComponent().isSelected() && return this.getComponent().isSelected();
!this.getComponent().getMimeTypesSelected().isEmpty();
} }
@Override @Override
public String getPredicate() throws FilterValidationException { public String getPredicate() throws FilterValidationException {
String predicate = ""; String predicate = "";
for(String mimeType : this.getComponent().getMimeTypesSelected()) { for (String mimeType : this.getComponent().getMimeTypesSelected()) {
predicate += "mime_type = '" + mimeType + "' OR "; predicate += "mime_type = '" + mimeType + "' OR ";
} }
if(predicate.length() > 3) { if (predicate.length() > 3) {
predicate = predicate.substring(0, predicate.length() - 3); predicate = predicate.substring(0, predicate.length() - 3);
} }
return predicate; return predicate;
@ -40,5 +40,9 @@ class MimeTypeFilter extends AbstractFileSearchFilter<MimeTypePanel> {
@Override @Override
public void addActionListener(ActionListener l) { public void addActionListener(ActionListener l) {
} }
@Override
public boolean isValid() {
return !this.getComponent().getMimeTypesSelected().isEmpty();
}
} }

View File

@ -31,7 +31,7 @@
<Group type="102" attributes="0"> <Group type="102" 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="jScrollPane1" pref="298" max="32767" attributes="0"/> <Component id="jScrollPane1" pref="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="jLabel1" min="-2" pref="246" max="-2" attributes="0"/> <Component id="jLabel1" min="-2" pref="246" max="-2" attributes="0"/>
<EmptySpace min="0" pref="0" max="32767" attributes="0"/> <EmptySpace min="0" pref="0" max="32767" attributes="0"/>

View File

@ -5,12 +5,16 @@
*/ */
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.apache.tika.mime.MediaType; import org.apache.tika.mime.MediaType;
import org.apache.tika.mime.MimeTypes; import org.apache.tika.mime.MimeTypes;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -25,6 +29,7 @@ public class MimeTypePanel extends javax.swing.JPanel {
private static final SortedSet<MediaType> mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes(); private static final SortedSet<MediaType> mediaTypes = MimeTypes.getDefaultMimeTypes().getMediaTypeRegistry().getTypes();
private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName()); private static final Logger logger = Logger.getLogger(MimeTypePanel.class.getName());
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/** /**
* Creates new form MimeTypePanel * Creates new form MimeTypePanel
@ -32,6 +37,12 @@ public class MimeTypePanel extends javax.swing.JPanel {
public MimeTypePanel() { public MimeTypePanel() {
initComponents(); initComponents();
setComponentsEnabled(); setComponentsEnabled();
this.mimeTypeList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
});
} }
private String[] getMimeTypeArray() { private String[] getMimeTypeArray() {
@ -75,6 +86,16 @@ public class MimeTypePanel extends javax.swing.JPanel {
this.mimeTypeList.setEnabled(enabled); this.mimeTypeList.setEnabled(enabled);
this.jLabel1.setEnabled(enabled); this.jLabel1.setEnabled(enabled);
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener pcl) {
pcs.addPropertyChangeListener(pcl);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener pcl) {
pcs.removePropertyChangeListener(pcl);
}
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
@ -141,6 +162,8 @@ public class MimeTypePanel extends javax.swing.JPanel {
private void mimeTypeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeTypeCheckBoxActionPerformed private void mimeTypeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_mimeTypeCheckBoxActionPerformed
setComponentsEnabled(); setComponentsEnabled();
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
this.mimeTypeList.setSelectedIndices(new int[0]);
}//GEN-LAST:event_mimeTypeCheckBoxActionPerformed }//GEN-LAST:event_mimeTypeCheckBoxActionPerformed

View File

@ -19,7 +19,6 @@
package org.sleuthkit.autopsy.filesearch; package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException; import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
@ -63,4 +62,9 @@ class NameSearchFilter extends AbstractFileSearchFilter<NameSearchPanel> {
public void addActionListener(ActionListener l) { public void addActionListener(ActionListener l) {
getComponent().addActionListener(l); getComponent().addActionListener(l);
} }
@Override
public boolean isValid() {
return !this.getComponent().getSearchTextField().getText().isEmpty();
}
} }

View File

@ -17,7 +17,7 @@
* limitations under the License. * limitations under the License.
*/ */
/* /*
* NameSearchPanel.java * NameSearchPanel.java
* *
* Created on Oct 19, 2011, 11:58:53 AM * Created on Oct 19, 2011, 11:58:53 AM
@ -26,9 +26,13 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JMenuItem; import javax.swing.JMenuItem;
import javax.swing.JTextField; import javax.swing.JTextField;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/** /**
* *
@ -36,6 +40,8 @@ import javax.swing.JTextField;
*/ */
class NameSearchPanel extends javax.swing.JPanel { class NameSearchPanel extends javax.swing.JPanel {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/** /**
* Creates new form NameSearchPanel * Creates new form NameSearchPanel
*/ */
@ -67,6 +73,22 @@ class NameSearchPanel extends javax.swing.JPanel {
copyMenuItem.addActionListener(actList); copyMenuItem.addActionListener(actList);
pasteMenuItem.addActionListener(actList); pasteMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList); selectAllMenuItem.addActionListener(actList);
this.searchTextField.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void insertUpdate(DocumentEvent e) {
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
@Override
public void removeUpdate(DocumentEvent e) {
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
@Override
public void changedUpdate(DocumentEvent e) {
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}
});
} }
@ -77,12 +99,22 @@ class NameSearchPanel extends javax.swing.JPanel {
JTextField getSearchTextField() { JTextField getSearchTextField() {
return searchTextField; return searchTextField;
} }
void setComponentsEnabled() { void setComponentsEnabled() {
boolean enabled = nameCheckBox.isSelected(); boolean enabled = nameCheckBox.isSelected();
this.searchTextField.setEnabled(enabled); this.searchTextField.setEnabled(enabled);
this.noteNameLabel.setEnabled(enabled); this.noteNameLabel.setEnabled(enabled);
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener pcl) {
pcs.addPropertyChangeListener(pcl);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener pcl) {
pcs.removePropertyChangeListener(pcl);
}
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
@ -168,6 +200,7 @@ class NameSearchPanel extends javax.swing.JPanel {
private void nameCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nameCheckBoxActionPerformed private void nameCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_nameCheckBoxActionPerformed
setComponentsEnabled(); setComponentsEnabled();
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_nameCheckBoxActionPerformed }//GEN-LAST:event_nameCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables

View File

@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.swing.JComboBox; import javax.swing.JComboBox;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException; import org.sleuthkit.autopsy.filesearch.FileSearchFilter.FilterValidationException;
@ -73,4 +72,9 @@ class SizeSearchFilter extends AbstractFileSearchFilter<SizeSearchPanel> {
public void addActionListener(ActionListener l) { public void addActionListener(ActionListener l) {
getComponent().addActionListener(l); getComponent().addActionListener(l);
} }
@Override
public boolean isValid() {
return true;
}
} }

View File

@ -20,6 +20,8 @@ package org.sleuthkit.autopsy.filesearch;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.text.NumberFormat; import java.text.NumberFormat;
import javax.swing.JCheckBox; import javax.swing.JCheckBox;
import javax.swing.JComboBox; import javax.swing.JComboBox;
@ -32,6 +34,8 @@ import javax.swing.JMenuItem;
*/ */
class SizeSearchPanel extends javax.swing.JPanel { class SizeSearchPanel extends javax.swing.JPanel {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
/** /**
* Creates new form SizeSearchPanel * Creates new form SizeSearchPanel
*/ */
@ -81,13 +85,23 @@ class SizeSearchPanel extends javax.swing.JPanel {
JComboBox<String> getSizeUnitComboBox() { JComboBox<String> getSizeUnitComboBox() {
return sizeUnitComboBox; return sizeUnitComboBox;
} }
void setComponentsEnabled() { void setComponentsEnabled() {
boolean enabled = this.sizeCheckBox.isSelected(); boolean enabled = this.sizeCheckBox.isSelected();
this.sizeCompareComboBox.setEnabled(enabled); this.sizeCompareComboBox.setEnabled(enabled);
this.sizeUnitComboBox.setEnabled(enabled); this.sizeUnitComboBox.setEnabled(enabled);
this.sizeTextField.setEnabled(enabled); this.sizeTextField.setEnabled(enabled);
} }
@Override
public void addPropertyChangeListener(PropertyChangeListener pcl) {
pcs.addPropertyChangeListener(pcl);
}
@Override
public void removePropertyChangeListener(PropertyChangeListener pcl) {
pcs.removePropertyChangeListener(pcl);
}
/** /**
* This method is called from within the constructor to initialize the form. * This method is called from within the constructor to initialize the form.
@ -168,6 +182,7 @@ class SizeSearchPanel extends javax.swing.JPanel {
private void sizeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sizeCheckBoxActionPerformed private void sizeCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sizeCheckBoxActionPerformed
setComponentsEnabled(); setComponentsEnabled();
pcs.firePropertyChange(FileSearchPanel.EVENT.CHECKED.toString(), null, null);
}//GEN-LAST:event_sizeCheckBoxActionPerformed }//GEN-LAST:event_sizeCheckBoxActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables // Variables declaration - do not modify//GEN-BEGIN:variables

View File

@ -32,9 +32,17 @@ import javax.swing.JOptionPane;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.Cancellable; import org.openide.util.Cancellable;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.IngestJobInfo;
import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
import org.sleuthkit.datamodel.IngestModuleInfo;
import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* Encapsulates a data source and the ingest module pipelines used to process * Encapsulates a data source and the ingest module pipelines used to process
@ -151,6 +159,8 @@ final class DataSourceIngestJob {
private ProgressHandle fileIngestProgress; private ProgressHandle fileIngestProgress;
private String currentFileIngestModule = ""; private String currentFileIngestModule = "";
private String currentFileIngestTask = ""; private String currentFileIngestTask = "";
private List<IngestModuleInfo> ingestModules = new ArrayList<>();
private IngestJobInfo ingestJob;
/** /**
* A data source ingest job uses this field to report its creation time. * A data source ingest job uses this field to report its creation time.
@ -243,6 +253,20 @@ final class DataSourceIngestJob {
*/ */
Thread.currentThread().interrupt(); Thread.currentThread().interrupt();
} }
SleuthkitCase skCase = Case.getCurrentCase().getSleuthkitCase();
try {
this.addIngestModules(firstStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
this.addIngestModules(fileIngestModuleTemplates, IngestModuleType.FILE_LEVEL, skCase);
this.addIngestModules(secondStageDataSourceModuleTemplates, IngestModuleType.DATA_SOURCE_LEVEL, skCase);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to add ingest modules to database.", ex);
}
}
private void addIngestModules(List<IngestModuleTemplate> templates, IngestModuleType type, SleuthkitCase skCase) throws TskCoreException {
for (IngestModuleTemplate module : templates) {
ingestModules.add(skCase.addIngestModule(module.getModuleName(), FactoryClassNameNormalizer.normalize(module.getModuleFactory().getClass().getCanonicalName()), type, module.getModuleFactory().getModuleVersionNumber()));
}
} }
/** /**
@ -365,6 +389,11 @@ final class DataSourceIngestJob {
logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS logger.log(Level.INFO, "Starting second stage analysis for {0} (jobId={1}), no first stage configured", new Object[]{dataSource.getName(), this.id}); //NON-NLS
this.startSecondStage(); this.startSecondStage();
} }
try {
this.ingestJob = Case.getCurrentCase().getSleuthkitCase().addIngestJob(dataSource, NetworkUtils.getLocalHostName(), ingestModules, new Date(this.createTime), new Date(0), IngestJobStatusType.STARTED, "");
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to add ingest job to database.", ex);
}
} }
return errors; return errors;
} }
@ -641,8 +670,26 @@ final class DataSourceIngestJob {
} }
} }
} }
if (this.cancelled) {
try {
ingestJob.setIngestJobStatus(IngestJobStatusType.CANCELLED);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
}
} else {
try {
ingestJob.setIngestJobStatus(IngestJobStatusType.COMPLETED);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to set ingest status for ingest job in database.", ex);
}
}
try {
this.ingestJob.setEndDateTime(new Date());
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Failed to set end date for ingest job in database.", ex);
}
this.parentJob.dataSourceJobFinished(this); this.parentJob.dataSourceJobFinished(this);
} }
/** /**

View File

@ -0,0 +1,42 @@
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.sleuthkit.autopsy.ingest;
import org.sleuthkit.autopsy.coreutils.Logger;
/**
* Used to strip python ids on factory class names.
*/
class FactoryClassNameNormalizer {
private static final CharSequence pythonModuleSettingsPrefixCS = "org.python.proxies.".subSequence(0, "org.python.proxies.".length() - 1); //NON-NLS
private static final Logger logger = Logger.getLogger(FactoryClassNameNormalizer.class.getName());
static String normalize(String canonicalClassName) {
if (isPythonModuleSettingsFile(canonicalClassName)) {
// compiled python modules have variable instance number as a part of their file name.
// This block of code gets rid of that variable instance number and helps maitains constant module name over multiple runs.
String moduleClassName = canonicalClassName.replaceAll("[$][\\d]", ""); //NON-NLS NON-NLS
return moduleClassName;
}
return canonicalClassName;
}
/**
* Determines if the moduleSettingsFilePath is that of a serialized jython
* instance. Serialized Jython instances (settings saved on the disk)
* contain "org.python.proxies." in their fileName based on the current
* implementation.
*
* @param moduleSettingsFilePath path to the module settings file.
*
* @return True or false
*/
private static boolean isPythonModuleSettingsFile(String moduleSettingsFilePath) {
return moduleSettingsFilePath.contains(pythonModuleSettingsPrefixCS);
}
}

View File

@ -33,10 +33,10 @@ import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.io.NbObjectInputStream; import org.openide.util.io.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream; import org.openide.util.io.NbObjectOutputStream;
import org.python.util.PythonObjectInputStream;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil; import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.python.util.PythonObjectInputStream;
/** /**
* Encapsulates the ingest job settings for a particular execution context. * Encapsulates the ingest job settings for a particular execution context.
@ -467,17 +467,9 @@ public class IngestJobSettings {
* @param settings The ingest job settings for the ingest module * @param settings The ingest job settings for the ingest module
*/ */
private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) { private void saveModuleSettings(IngestModuleFactory factory, IngestModuleIngestJobSettings settings) {
try { String moduleSettingsFilePath = Paths.get(this.moduleSettingsFolderPath, FactoryClassNameNormalizer.normalize(factory.getClass().getCanonicalName()) + MODULE_SETTINGS_FILE_EXT).toString();
String moduleSettingsFilePath = getModuleSettingsFilePath(factory); try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
// compiled python modules have substring org.python.proxies. It can be used to identify them. out.writeObject(settings);
if (isPythonModuleSettingsFile(moduleSettingsFilePath)) {
// compiled python modules have variable instance number as a part of their file name.
// This block of code gets rid of that variable instance number and helps maitains constant module name over multiple runs.
moduleSettingsFilePath = moduleSettingsFilePath.replaceAll("[$][\\d]+.settings$", "\\$.settings"); //NON-NLS NON-NLS
}
try (NbObjectOutputStream out = new NbObjectOutputStream(new FileOutputStream(moduleSettingsFilePath))) {
out.writeObject(settings);
}
} catch (IOException ex) { } catch (IOException ex) {
String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS String warning = NbBundle.getMessage(IngestJobSettings.class, "IngestJobSettings.moduleSettingsSave.warning", factory.getModuleDisplayName(), this.executionContext); //NON-NLS
logger.log(Level.SEVERE, warning, ex); logger.log(Level.SEVERE, warning, ex);

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 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");
@ -23,7 +23,9 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
/** /**
* * An implementation of a keyword search service.
*
* TODO (AUT-2158: This interface should not extend Closeable.
*/ */
public interface KeywordSearchService extends Closeable { public interface KeywordSearchService extends Closeable {
@ -49,4 +51,4 @@ public interface KeywordSearchService extends Closeable {
*/ */
public void tryConnect(String host, int port) throws KeywordSearchServiceException; public void tryConnect(String host, int port) throws KeywordSearchServiceException;
} }

View File

@ -26,7 +26,6 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
@ -72,6 +71,7 @@ class BrowserLocationAnalyzer {
} }
} }
@NbBundle.Messages({"BrowserLocationAnalyzer.indexError.message=Failed to index GPS trackpoint artifact for keyword search."})
private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) { private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) {
Connection connection = null; Connection connection = null;
ResultSet resultSet = null; ResultSet resultSet = null;
@ -110,9 +110,9 @@ class BrowserLocationAnalyzer {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactTypeName(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.BrowserLocationAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -25,8 +25,8 @@ import java.math.BigInteger;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
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.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -78,6 +78,7 @@ class CacheLocationAnalyzer {
} }
} }
@Messages({"CacheLocationAnalyzer.indexError.message=Failed to index GPS trackpoint artifact for keyword search."})
private static void findGeoLocationsInFile(File file, AbstractFile f) { private static void findGeoLocationsInFile(File file, AbstractFile f) {
byte[] bytes; // will temporarily hold bytes to be converted into the correct data types byte[] bytes; // will temporarily hold bytes to be converted into the correct data types
@ -140,14 +141,13 @@ class CacheLocationAnalyzer {
//Not storing these for now. //Not storing these for now.
// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy)); // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),moduleName, accuracy));
// bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence)); // bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID(),moduleName, confidence));
try { try {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.CacheLocationAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }

View File

@ -28,7 +28,7 @@ import java.sql.Statement;
import java.util.Arrays; import java.util.Arrays;
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.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -58,7 +58,7 @@ class CallLogAnalyzer {
private static final Iterable<String> tableNames = Arrays.asList("calls", "logs"); //NON-NLS private static final Iterable<String> tableNames = Arrays.asList("calls", "logs"); //NON-NLS
public static void findCallLogs(Content dataSource, FileManager fileManager) { public static void findCallLogs(Content dataSource, FileManager fileManager) {
blackboard = Case.getCurrentCase().getServices().getBlackboard(); blackboard = Case.getCurrentCase().getServices().getBlackboard();
try { try {
List<AbstractFile> absFiles = fileManager.findFiles(dataSource, "logs.db"); //NON-NLS List<AbstractFile> absFiles = fileManager.findFiles(dataSource, "logs.db"); //NON-NLS
absFiles.addAll(fileManager.findFiles(dataSource, "contacts.db")); //NON-NLS absFiles.addAll(fileManager.findFiles(dataSource, "contacts.db")); //NON-NLS
@ -77,6 +77,7 @@ class CallLogAnalyzer {
} }
} }
@Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."})
private static void findCallLogsInDB(String DatabasePath, AbstractFile f) { private static void findCallLogsInDB(String DatabasePath, AbstractFile f) {
if (DatabasePath == null || DatabasePath.isEmpty()) { if (DatabasePath == null || DatabasePath.isEmpty()) {
@ -113,16 +114,16 @@ class CallLogAnalyzer {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName());
} }
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex); //NON-NLS logger.log(Level.SEVERE, "Error posting call log record to the Blackboard", ex); //NON-NLS
} }
} }
} catch (SQLException e) { } catch (SQLException e) {
logger.log(Level.WARNING, "Could not read table {0} in db {1}", new Object[]{tableName, DatabasePath}); //NON-NLS logger.log(Level.WARNING, String.format("Could not read table %s in db %s", tableName, DatabasePath), e); //NON-NLS
} }
} }
} catch (SQLException e) { } catch (SQLException e) {

View File

@ -27,7 +27,7 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -79,6 +79,7 @@ class ContactAnalyzer {
* path The fileId will be the Abstract file associated * path The fileId will be the Abstract file associated
* with the artifacts * with the artifacts
*/ */
@Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."})
private static void findContactsInDB(String databasePath, AbstractFile f) { private static void findContactsInDB(String databasePath, AbstractFile f) {
Connection connection = null; Connection connection = null;
ResultSet resultSet = null; ResultSet resultSet = null;
@ -154,9 +155,9 @@ class ContactAnalyzer {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }

View File

@ -26,8 +26,8 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -71,6 +71,7 @@ class GoogleMapLocationAnalyzer {
} }
} }
@Messages({"GoogleMapLocationAnalyzer.indexError.message=Failed to index GPS route artifact for keyword search."})
private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) { private static void findGeoLocationsInDB(String DatabasePath, AbstractFile f) {
Connection connection = null; Connection connection = null;
ResultSet resultSet = null; ResultSet resultSet = null;
@ -136,9 +137,9 @@ class GoogleMapLocationAnalyzer {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.GoogleMapLocationAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -28,6 +28,7 @@ import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -68,6 +69,7 @@ class TangoMessageAnalyzer {
} }
} }
@Messages({"TangoMessageAnalyzer.indexError.message=Failed to index Tango message artifact for keyword search."})
private static void findTangoMessagesInDB(String DatabasePath, AbstractFile f) { private static void findTangoMessagesInDB(String DatabasePath, AbstractFile f) {
Connection connection = null; Connection connection = null;
ResultSet resultSet = null; ResultSet resultSet = null;
@ -110,14 +112,14 @@ class TangoMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
NbBundle.getMessage(TangoMessageAnalyzer.class, NbBundle.getMessage(TangoMessageAnalyzer.class,
"TangoMessageAnalyzer.bbAttribute.tangoMessage"))); "TangoMessageAnalyzer.bbAttribute.tangoMessage")));
try { try {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.TangoMessageAnalyzer_indexError_message(), bba.getDisplayName());
logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -26,8 +26,8 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -68,6 +68,7 @@ class TextMessageAnalyzer {
} }
} }
@Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."})
private static void findTextsInDB(String DatabasePath, AbstractFile f) { private static void findTextsInDB(String DatabasePath, AbstractFile f) {
Connection connection = null; Connection connection = null;
ResultSet resultSet = null; ResultSet resultSet = null;
@ -123,14 +124,14 @@ class TextMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
NbBundle.getMessage(TextMessageAnalyzer.class, NbBundle.getMessage(TextMessageAnalyzer.class,
"TextMessageAnalyzer.bbAttribute.smsMessage"))); "TextMessageAnalyzer.bbAttribute.smsMessage")));
try { try {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -26,8 +26,8 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -71,6 +71,7 @@ class WWFMessageAnalyzer {
} }
} }
@Messages({"WWFMessageAnalyzer.indexError.message=Failed to index WWF message artifact for keyword search."})
private static void findWWFMessagesInDB(String DatabasePath, AbstractFile f) { private static void findWWFMessagesInDB(String DatabasePath, AbstractFile f) {
Connection connection = null; Connection connection = null;
ResultSet resultSet = null; ResultSet resultSet = null;
@ -110,14 +111,14 @@ class WWFMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName,
NbBundle.getMessage(WWFMessageAnalyzer.class, NbBundle.getMessage(WWFMessageAnalyzer.class,
"WWFMessageAnalyzer.bbAttribute.wordsWithFriendsMsg"))); "WWFMessageAnalyzer.bbAttribute.wordsWithFriendsMsg")));
try { try {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.WWFMessageAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -42,6 +42,7 @@ import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem; import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.casemodule.services.FileManager; import org.sleuthkit.autopsy.casemodule.services.FileManager;
@ -50,7 +51,6 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException;
import org.sleuthkit.autopsy.ingest.IngestMonitor; import org.sleuthkit.autopsy.ingest.IngestMonitor;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
@ -267,6 +267,7 @@ class SevenZipExtractor {
* *
* @return list of unpacked derived files * @return list of unpacked derived files
*/ */
@Messages({"SevenZipExtractor.indexError.message=Failed to index encryption detected artifact for keyword search."})
void unpack(AbstractFile archiveFile) { void unpack(AbstractFile archiveFile) {
blackboard = Case.getCurrentCase().getServices().getBlackboard(); blackboard = Case.getCurrentCase().getServices().getBlackboard();
String archiveFilePath; String archiveFilePath;
@ -586,9 +587,9 @@ class SevenZipExtractor {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(artifact); blackboard.indexArtifact(artifact);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", artifact.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), artifact.getDisplayName()); Bundle.SevenZipExtractor_indexError_message(), artifact.getDisplayName());
} }
services.fireModuleDataEvent(new ModuleDataEvent(EmbeddedFileExtractorModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED)); services.fireModuleDataEvent(new ModuleDataEvent(EmbeddedFileExtractorModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED));

View File

@ -38,15 +38,16 @@ import java.util.TimeZone;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
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.autopsy.modules.filetypeid.FileTypeDetector; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -133,6 +134,7 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
return processFile(content); return processFile(content);
} }
@Messages({"ExifParserFileIngestModule.indexError.message=Failed to index EXIF Metadata artifact for keyword search."})
ProcessResult processFile(AbstractFile f) { ProcessResult processFile(AbstractFile f) {
InputStream in = null; InputStream in = null;
BufferedInputStream bin = null; BufferedInputStream bin = null;
@ -206,9 +208,9 @@ public final class ExifParserFileIngestModule implements FileIngestModule {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.ExifParserFileIngestModule_indexError_message(), bba.getDisplayName());
} }
filesToFire = true; filesToFire = true;
} }

View File

@ -23,6 +23,7 @@ import java.util.HashMap;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -105,6 +106,7 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
} }
@Override @Override
@Messages({"FileExtMismatchIngestModule.indexError.message=Failed to index file extension mismatch artifact for keyword search."})
public ProcessResult process(AbstractFile abstractFile) { public ProcessResult process(AbstractFile abstractFile) {
blackboard = Case.getCurrentCase().getServices().getBlackboard(); blackboard = Case.getCurrentCase().getServices().getBlackboard();
if (this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) { if (this.settings.skipKnownFiles() && (abstractFile.getKnown() == FileKnown.KNOWN)) {
@ -139,9 +141,9 @@ public class FileExtMismatchIngestModule implements FileIngestModule {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bart); blackboard.indexArtifact(bart);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bart.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bart.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bart.getDisplayName()); Bundle.FileExtMismatchIngestModule_indexError_message(), bart.getDisplayName());
} }
services.fireModuleDataEvent(new ModuleDataEvent(FileExtMismatchDetectorModuleFactory.getModuleName(), ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED, Collections.singletonList(bart))); services.fireModuleDataEvent(new ModuleDataEvent(FileExtMismatchDetectorModuleFactory.getModuleName(), ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED, Collections.singletonList(bart)));

View File

@ -104,6 +104,19 @@ final class CustomFileTypesManager {
return customTypes; return customTypes;
} }
/**
* Gets the custom file types defined by Autopsy.
*
* @return A list of custom file types, possibly empty.
*/
synchronized List<FileType> getAutopsyDefinedFileTypes() {
/**
* It is safe to return references instead of copies in this snapshot
* because FileType objects are immutable.
*/
return new ArrayList<>(autopsyDefinedFileTypes);
}
/** /**
* Gets the user-defined custom file types. * Gets the user-defined custom file types.
* *
@ -287,6 +300,15 @@ final class CustomFileTypesManager {
fileType = new FileType("application/x-iff", signatureList); //NON-NLS fileType = new FileType("application/x-iff", signatureList); //NON-NLS
autopsyDefinedFileTypes.add(fileType); autopsyDefinedFileTypes.add(fileType);
/*
* Add type for .tec files with leading End Of Image marker (JFIF JPEG)
*/
byteArray = DatatypeConverter.parseHexBinary("FFD9FFD8"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("image/jpeg", signatureList); //NON-NLS
autopsyDefinedFileTypes.add(fileType);
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
/* /*
* parseHexBinary() throws this if the argument passed in is not hex * parseHexBinary() throws this if the argument passed in is not hex

View File

@ -56,8 +56,8 @@ public class FileTypeDetector {
*/ */
public FileTypeDetector() throws FileTypeDetectorInitException { public FileTypeDetector() throws FileTypeDetectorInitException {
try { try {
userDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes(); userDefinedFileTypes = CustomFileTypesManager.getInstance().getUserDefinedFileTypes();
autopsyDefinedFileTypes = CustomFileTypesManager.getInstance().getFileTypes(); autopsyDefinedFileTypes = CustomFileTypesManager.getInstance().getAutopsyDefinedFileTypes();
} catch (CustomFileTypesManager.CustomFileTypesException ex) { } catch (CustomFileTypesManager.CustomFileTypesException ex) {
throw new FileTypeDetectorInitException("Error loading custom file types", ex); //NON-NLS throw new FileTypeDetectorInitException("Error loading custom file types", ex); //NON-NLS
} }
@ -168,7 +168,7 @@ public class FileTypeDetector {
/** /**
* Detects the MIME type of a file. The result is saved to the case database * Detects the MIME type of a file. The result is saved to the case database
* only if the add to case dastabase flag is set. * only if the add to case database flag is set.
* *
* @param file The file to test. * @param file The file to test.
* @param addToCaseDb Whether the MIME type should be added to the case * @param addToCaseDb Whether the MIME type should be added to the case

View File

@ -25,22 +25,24 @@
<DimensionLayout dim="0"> <DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<Component id="jPanel3" max="32767" attributes="0"/> <Component id="jPanel3" pref="752" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/> <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Component id="jPanel3" alignment="0" pref="345" max="32767" attributes="0"/>
<Component id="jPanel3" max="32767" attributes="0"/>
<EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
</Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
</Layout> </Layout>
<SubComponents> <SubComponents>
<Container class="javax.swing.JPanel" name="jPanel3"> <Container class="javax.swing.JPanel" name="jPanel3">
<Properties>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[781, 339]"/>
</Property>
</Properties>
<Layout> <Layout>
<DimensionLayout dim="0"> <DimensionLayout dim="0">
@ -62,7 +64,7 @@
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jLabel3" min="-2" max="-2" attributes="0"/> <Component id="jLabel3" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane2" max="32767" attributes="0"/> <Component id="jScrollPane2" pref="281" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="ingestRunningWarningLabel" min="-2" pref="16" max="-2" attributes="0"/> <Component id="ingestRunningWarningLabel" min="-2" pref="16" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
@ -101,7 +103,10 @@
<Container class="javax.swing.JScrollPane" name="jScrollPane2"> <Container class="javax.swing.JScrollPane" name="jScrollPane2">
<Properties> <Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 100]"/> <Dimension value="[300, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[550, 275]"/>
</Property> </Property>
</Properties> </Properties>
@ -110,7 +115,7 @@
<Container class="javax.swing.JSplitPane" name="jSplitPane1"> <Container class="javax.swing.JSplitPane" name="jSplitPane1">
<Properties> <Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[558, 285]"/> <Dimension value="[0, 0]"/>
</Property> </Property>
</Properties> </Properties>
@ -119,7 +124,10 @@
<Container class="javax.swing.JPanel" name="jPanel1"> <Container class="javax.swing.JPanel" name="jPanel1">
<Properties> <Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[362, 283]"/> <Dimension value="[362, 0]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[362, 0]"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -154,14 +162,14 @@
<EmptySpace min="-2" pref="12" max="-2" attributes="0"/> <EmptySpace min="-2" pref="12" max="-2" attributes="0"/>
<Component id="jLabel2" min="-2" max="-2" attributes="0"/> <Component id="jLabel2" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="typesScrollPane" pref="397" max="32767" attributes="0"/> <Component id="typesScrollPane" pref="203" max="32767" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="10" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0"> <Group type="103" groupAlignment="3" attributes="0">
<Component id="newTypeButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="newTypeButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="editTypeButton" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="editTypeButton" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="deleteTypeButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/> <Component id="deleteTypeButton" linkSize="2" alignment="3" min="-2" max="-2" attributes="0"/>
</Group> </Group>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -263,7 +271,7 @@
<Container class="javax.swing.JPanel" name="jPanel2"> <Container class="javax.swing.JPanel" name="jPanel2">
<Properties> <Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[79, 283]"/> <Dimension value="[79, 0]"/>
</Property> </Property>
</Properties> </Properties>
<Constraints> <Constraints>
@ -291,11 +299,11 @@
<DimensionLayout dim="1"> <DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0"> <Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/> <EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="400" max="32767" attributes="0"/> <Component id="jLabel1" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" pref="40" max="-2" attributes="0"/> <EmptySpace max="-2" attributes="0"/>
<Component id="jScrollPane1" pref="235" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group> </Group>
</Group> </Group>
</DimensionLayout> </DimensionLayout>
@ -320,6 +328,7 @@
<Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> <Property name="model" type="javax.swing.ListModel" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="new javax.swing.AbstractListModel&lt;Signature&gt;() {&#xa; Signature[] signatures = {};&#xa; public int getSize() { return signatures.length; }&#xa; public Signature getElementAt(int i) { return signatures[i]; }&#xa;}" type="code"/> <Connection code="new javax.swing.AbstractListModel&lt;Signature&gt;() {&#xa; Signature[] signatures = {};&#xa; public int getSize() { return signatures.length; }&#xa; public Signature getElementAt(int i) { return signatures[i]; }&#xa;}" type="code"/>
</Property> </Property>
<Property name="enabled" type="boolean" value="false"/>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor"> <Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[32767, 32767]"/> <Dimension value="[32767, 32767]"/>
</Property> </Property>

View File

@ -36,8 +36,8 @@ import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel; import org.sleuthkit.autopsy.ingest.IngestModuleGlobalSettingsPanel;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
import org.sleuthkit.autopsy.modules.filetypeid.CustomFileTypesManager.CustomFileTypesException; import org.sleuthkit.autopsy.modules.filetypeid.CustomFileTypesManager.CustomFileTypesException;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
/** /**
* A panel to allow a user to make custom file type definitions. In addition to * A panel to allow a user to make custom file type definitions. In addition to
@ -329,6 +329,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
setMaximumSize(null); setMaximumSize(null);
setPreferredSize(new java.awt.Dimension(752, 507)); setPreferredSize(new java.awt.Dimension(752, 507));
jPanel3.setPreferredSize(new java.awt.Dimension(781, 339));
ingestRunningWarningLabel.setFont(ingestRunningWarningLabel.getFont().deriveFont(ingestRunningWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); ingestRunningWarningLabel.setFont(ingestRunningWarningLabel.getFont().deriveFont(ingestRunningWarningLabel.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
ingestRunningWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/filetypeid/warning16.png"))); // NOI18N ingestRunningWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/filetypeid/warning16.png"))); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(ingestRunningWarningLabel, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(ingestRunningWarningLabel, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.ingestRunningWarningLabel.text")); // NOI18N
@ -336,11 +338,13 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
jLabel3.setFont(jLabel3.getFont().deriveFont(jLabel3.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); jLabel3.setFont(jLabel3.getFont().deriveFont(jLabel3.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel3.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel3.text")); // NOI18N
jScrollPane2.setMinimumSize(new java.awt.Dimension(300, 100)); jScrollPane2.setMinimumSize(new java.awt.Dimension(300, 0));
jScrollPane2.setPreferredSize(new java.awt.Dimension(550, 275));
jSplitPane1.setMinimumSize(new java.awt.Dimension(558, 285)); jSplitPane1.setMinimumSize(new java.awt.Dimension(0, 0));
jPanel1.setMinimumSize(new java.awt.Dimension(362, 283)); jPanel1.setMinimumSize(new java.awt.Dimension(362, 0));
jPanel1.setPreferredSize(new java.awt.Dimension(362, 0));
jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11)); jLabel2.setFont(jLabel2.getFont().deriveFont(jLabel2.getFont().getStyle() & ~java.awt.Font.BOLD, 11));
org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel2.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel2.text")); // NOI18N
@ -399,20 +403,20 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
.addGap(12, 12, 12) .addGap(12, 12, 12)
.addComponent(jLabel2) .addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(typesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 397, Short.MAX_VALUE) .addComponent(typesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 203, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGap(10, 10, 10)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(newTypeButton) .addComponent(newTypeButton)
.addComponent(editTypeButton) .addComponent(editTypeButton)
.addComponent(deleteTypeButton)) .addComponent(deleteTypeButton))
.addContainerGap()) .addGap(7, 7, 7))
); );
jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteTypeButton, newTypeButton}); jPanel1Layout.linkSize(javax.swing.SwingConstants.VERTICAL, new java.awt.Component[] {deleteTypeButton, newTypeButton});
jSplitPane1.setLeftComponent(jPanel1); jSplitPane1.setLeftComponent(jPanel1);
jPanel2.setMinimumSize(new java.awt.Dimension(79, 283)); jPanel2.setMinimumSize(new java.awt.Dimension(79, 0));
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel1.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.jLabel1.text")); // NOI18N
@ -421,6 +425,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
public int getSize() { return signatures.length; } public int getSize() { return signatures.length; }
public Signature getElementAt(int i) { return signatures[i]; } public Signature getElementAt(int i) { return signatures[i]; }
}); });
signatureList.setEnabled(false);
signatureList.setMaximumSize(new java.awt.Dimension(32767, 32767)); signatureList.setMaximumSize(new java.awt.Dimension(32767, 32767));
signatureList.setPreferredSize(null); signatureList.setPreferredSize(null);
jScrollPane1.setViewportView(signatureList); jScrollPane1.setViewportView(signatureList);
@ -444,8 +449,8 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
.addContainerGap() .addContainerGap()
.addComponent(jLabel1) .addComponent(jLabel1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE) .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)
.addGap(40, 40, 40)) .addContainerGap())
); );
jSplitPane1.setRightComponent(jPanel2); jSplitPane1.setRightComponent(jPanel2);
@ -470,7 +475,7 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
.addContainerGap() .addContainerGap()
.addComponent(jLabel3) .addComponent(jLabel3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 281, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(ingestRunningWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap()) .addContainerGap())
@ -481,14 +486,12 @@ final class FileTypeIdGlobalSettingsPanel extends IngestModuleGlobalSettingsPane
layout.setHorizontalGroup( layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addGroup(layout.createSequentialGroup()
.addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, 752, Short.MAX_VALUE)
.addGap(0, 0, 0)) .addGap(0, 0, 0))
); );
layout.setVerticalGroup( layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup() .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, 345, Short.MAX_VALUE)
.addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
); );
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents

View File

@ -22,6 +22,7 @@ import java.awt.Dimension;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JFrame; import javax.swing.JFrame;
@ -30,6 +31,7 @@ import org.apache.commons.io.FilenameUtils;
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.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
@ -273,12 +275,17 @@ final class HashDbCreateDatabaseDialog extends javax.swing.JDialog {
private void saveAsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsButtonActionPerformed private void saveAsButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveAsButtonActionPerformed
try { try {
String lastBaseDirectory = ""; String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) { if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY); lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
} }
StringBuilder path = new StringBuilder(); StringBuilder path = new StringBuilder();
path.append(lastBaseDirectory); path.append(lastBaseDirectory);
File hashDbFolder = new File(path.toString());
// create the folder if it doesn't exist
if (!hashDbFolder.exists()){
hashDbFolder.mkdir();
}
if (!hashSetNameTextField.getText().isEmpty()) { if (!hashSetNameTextField.getText().isEmpty()) {
path.append(File.separator).append(hashSetNameTextField.getText()); path.append(File.separator).append(hashSetNameTextField.getText());
} else { } else {

View File

@ -22,6 +22,7 @@ import java.awt.Dimension;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import javax.swing.JFrame; import javax.swing.JFrame;
@ -31,6 +32,7 @@ import org.apache.commons.io.FilenameUtils;
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.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
@ -249,9 +251,16 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) { if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
fileChooser.setCurrentDirectory(new File(ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY))); lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
} }
File hashDbFolder = new File(lastBaseDirectory);
// create the folder if it doesn't exist
if (!hashDbFolder.exists()) {
hashDbFolder.mkdir();
}
fileChooser.setCurrentDirectory(hashDbFolder);
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
File databaseFile = fileChooser.getSelectedFile(); File databaseFile = fileChooser.getSelectedFile();
try { try {

View File

@ -26,27 +26,28 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicLong; 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.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
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.modules.hashdatabase.HashDbManager.HashDb;
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.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.HashHitInfo;
import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.HashUtility;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskException; import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.datamodel.HashHitInfo;
@NbBundle.Messages({ @NbBundle.Messages({
"HashDbIngestModule.noKnownBadHashDbSetMsg=No known bad hash database set.", "HashDbIngestModule.noKnownBadHashDbSetMsg=No known bad hash database set.",
@ -285,6 +286,7 @@ public class HashDbIngestModule implements FileIngestModule {
return ret; return ret;
} }
@Messages({"HashDbIngestModule.indexError.message=Failed to index hashset hit artifact for keyword search."})
private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, boolean showInboxMessage) { private void postHashSetHitToBlackboard(AbstractFile abstractFile, String md5Hash, String hashSetName, String comment, boolean showInboxMessage) {
try { try {
String MODULE_NAME = NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.moduleName"); String MODULE_NAME = NbBundle.getMessage(HashDbIngestModule.class, "HashDbIngestModule.moduleName");
@ -303,9 +305,9 @@ public class HashDbIngestModule implements FileIngestModule {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(badFile); blackboard.indexArtifact(badFile);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", badFile.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + badFile.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), badFile.getDisplayName()); Bundle.HashDbIngestModule_indexError_message(), badFile.getDisplayName());
} }
if (showInboxMessage) { if (showInboxMessage) {

View File

@ -25,7 +25,7 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -74,6 +74,7 @@ class CallLogAnalyzer {
} }
} }
@Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."})
private void findCallLogsInDB(String DatabasePath, long fId) { private void findCallLogsInDB(String DatabasePath, long fId) {
if (DatabasePath == null || DatabasePath.isEmpty()) { if (DatabasePath == null || DatabasePath.isEmpty()) {
return; return;
@ -128,9 +129,9 @@ class CallLogAnalyzer {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -30,18 +30,18 @@ import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
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.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
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;
import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.ReadContentInputStream;
class ContactAnalyzer { class ContactAnalyzer {
@ -91,6 +91,7 @@ class ContactAnalyzer {
* path The fileId will be the Abstract file associated * path The fileId will be the Abstract file associated
* with the artifacts * with the artifacts
*/ */
@Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."})
private void findContactsInDB(String DatabasePath, long fId) { private void findContactsInDB(String DatabasePath, long fId) {
if (DatabasePath == null || DatabasePath.isEmpty()) { if (DatabasePath == null || DatabasePath.isEmpty()) {
return; return;
@ -149,9 +150,9 @@ class ContactAnalyzer {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }

View File

@ -26,6 +26,7 @@ import java.sql.Statement;
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.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -74,6 +75,7 @@ class TextMessageAnalyzer {
} }
} }
@Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."})
private void findTextsInDB(String DatabasePath, long fId) { private void findTextsInDB(String DatabasePath, long fId) {
if (DatabasePath == null || DatabasePath.isEmpty()) { if (DatabasePath == null || DatabasePath.isEmpty()) {
return; return;
@ -127,14 +129,14 @@ class TextMessageAnalyzer {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject));
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body)); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body));
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.smsMessage"))); bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.smsMessage")));
try { try {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName()); Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName());
} }
} }

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
@ -100,6 +99,7 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
* @inheritDoc * @inheritDoc
*/ */
@Override @Override
@Messages({"FilesIdentifierIngestModule.indexError.message=Failed to index interesting file hit artifact for keyword search."})
public ProcessResult process(AbstractFile file) { public ProcessResult process(AbstractFile file) {
blackboard = Case.getCurrentCase().getServices().getBlackboard(); blackboard = Case.getCurrentCase().getServices().getBlackboard();
@ -131,9 +131,8 @@ final class FilesIdentifierIngestModule implements FileIngestModule {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(artifact); blackboard.indexArtifact(artifact);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", artifact.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + artifact.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(Bundle.FilesIdentifierIngestModule_indexError_message(), artifact.getDisplayName());
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), artifact.getDisplayName());
} }
IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Collections.singletonList(artifact))); IngestServices.getInstance().fireModuleDataEvent(new ModuleDataEvent(moduleName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT, Collections.singletonList(artifact)));

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 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");
@ -30,9 +30,9 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level; import java.util.logging.Level;
@ -40,29 +40,25 @@ import org.openide.modules.InstalledFileLocator;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.autopsy.coreutils.ExecUtil;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.datamodel.ContentUtils; import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.ingest.FileIngestModule; import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.FileIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestModule; import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.Image;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.Volume;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.UNCPathUtilities;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
import org.sleuthkit.autopsy.ingest.FileIngestModuleProcessTerminator;
import org.sleuthkit.autopsy.ingest.IngestMonitor; import org.sleuthkit.autopsy.ingest.IngestMonitor;
import org.sleuthkit.autopsy.ingest.IngestServices; import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.autopsy.ingest.ModuleContentEvent;
import org.sleuthkit.autopsy.ingest.ProcTerminationCode;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.TskData;
/** /**
* A file ingest module that runs the Unallocated Carver executable with * A file ingest module that runs the Unallocated Carver executable with
@ -182,12 +178,6 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
Path tempFilePath = null; Path tempFilePath = null;
try { try {
long id = getRootId(file);
// make sure we have a valid systemID
if (id == -1) {
return IngestModule.ProcessResult.ERROR;
}
// Verify initialization succeeded. // Verify initialization succeeded.
if (null == this.executableFile) { if (null == this.executableFile) {
logger.log(Level.SEVERE, "PhotoRec carver called after failed start up"); // NON-NLS logger.log(Level.SEVERE, "PhotoRec carver called after failed start up"); // NON-NLS
@ -205,6 +195,12 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
NbBundle.getMessage(this.getClass(), "PhotoRecIngestModule.NotEnoughDiskSpace")); NbBundle.getMessage(this.getClass(), "PhotoRecIngestModule.NotEnoughDiskSpace"));
return IngestModule.ProcessResult.ERROR; return IngestModule.ProcessResult.ERROR;
} }
if (this.context.fileIngestIsCancelled() == true) {
// if it was cancelled by the user, result is OK
logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
return IngestModule.ProcessResult.OK;
}
// Write the file to disk. // Write the file to disk.
long writestart = System.currentTimeMillis(); long writestart = System.currentTimeMillis();
@ -212,6 +208,13 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
tempFilePath = Paths.get(paths.getTempDirPath().toString(), file.getName()); tempFilePath = Paths.get(paths.getTempDirPath().toString(), file.getName());
ContentUtils.writeToFile(file, tempFilePath.toFile()); ContentUtils.writeToFile(file, tempFilePath.toFile());
if (this.context.fileIngestIsCancelled() == true) {
// if it was cancelled by the user, result is OK
logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
return IngestModule.ProcessResult.OK;
}
// Create a subdirectory for this file. // Create a subdirectory for this file.
Path outputDirPath = Paths.get(paths.getOutputDirPath().toString(), file.getName()); Path outputDirPath = Paths.get(paths.getOutputDirPath().toString(), file.getName());
Files.createDirectory(outputDirPath); Files.createDirectory(outputDirPath);
@ -262,6 +265,12 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
java.io.File newAuditFile = new java.io.File(Paths.get(outputDirPath.toString(), PHOTOREC_REPORT).toString()); //NON-NLS java.io.File newAuditFile = new java.io.File(Paths.get(outputDirPath.toString(), PHOTOREC_REPORT).toString()); //NON-NLS
oldAuditFile.renameTo(newAuditFile); oldAuditFile.renameTo(newAuditFile);
if (this.context.fileIngestIsCancelled() == true) {
// if it was cancelled by the user, result is OK
logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
return IngestModule.ProcessResult.OK;
}
Path pathToRemove = Paths.get(outputDirPath.toAbsolutePath().toString()); Path pathToRemove = Paths.get(outputDirPath.toAbsolutePath().toString());
try (DirectoryStream<Path> stream = Files.newDirectoryStream(pathToRemove)) { try (DirectoryStream<Path> stream = Files.newDirectoryStream(pathToRemove)) {
for (Path entry : stream) { for (Path entry : stream) {
@ -276,10 +285,16 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
// Now that we've cleaned up the folders and data files, parse the xml output file to add carved items into the database // Now that we've cleaned up the folders and data files, parse the xml output file to add carved items into the database
long calcstart = System.currentTimeMillis(); long calcstart = System.currentTimeMillis();
PhotoRecCarverOutputParser parser = new PhotoRecCarverOutputParser(outputDirPath); PhotoRecCarverOutputParser parser = new PhotoRecCarverOutputParser(outputDirPath);
List<LayoutFile> carvedItems = parser.parse(newAuditFile, id, file); if (this.context.fileIngestIsCancelled() == true) {
// if it was cancelled by the user, result is OK
logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
return IngestModule.ProcessResult.OK;
}
List<LayoutFile> carvedItems = parser.parse(newAuditFile, file, context);
long calcdelta = (System.currentTimeMillis() - calcstart); long calcdelta = (System.currentTimeMillis() - calcstart);
totals.totalParsetime.addAndGet(calcdelta); totals.totalParsetime.addAndGet(calcdelta);
if (carvedItems != null) { // if there were any results from carving, add the unallocated carving event to the reports list. if (carvedItems != null && !carvedItems.isEmpty()) { // if there were any results from carving, add the unallocated carving event to the reports list.
totals.totalItemsRecovered.addAndGet(carvedItems.size()); totals.totalItemsRecovered.addAndGet(carvedItems.size());
context.addFilesToJob(new ArrayList<>(carvedItems)); context.addFilesToJob(new ArrayList<>(carvedItems));
services.fireModuleContentEvent(new ModuleContentEvent(carvedItems.get(0))); // fire an event to update the tree services.fireModuleContentEvent(new ModuleContentEvent(carvedItems.get(0))); // fire an event to update the tree
@ -411,31 +426,6 @@ final class PhotoRecCarverFileIngestModule implements FileIngestModule {
return path; return path;
} }
/**
* Finds the root Volume or Image of the AbstractFile passed in.
*
* @param file The file we want to find the root parent for
*
* @return The ID of the root parent Volume or Image
*/
private static long getRootId(AbstractFile file) {
long id = -1;
Content parent = null;
try {
parent = file.getParent();
while (parent != null) {
if (parent instanceof Volume || parent instanceof Image) {
id = parent.getId();
break;
}
parent = parent.getParent();
}
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "PhotoRec carver exception while trying to get parent of AbstractFile.", ex); //NON-NLS
}
return id;
}
/** /**
* Finds and returns the path to the executable, if able. * Finds and returns the path to the executable, if able.
* *

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2014 Basis Technology Corp. * Copyright 2011-2016 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");
@ -27,13 +27,16 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
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.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.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.XMLUtil; import org.sleuthkit.autopsy.coreutils.XMLUtil;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.CarvingResult;
import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LayoutFile;
import org.sleuthkit.datamodel.CarvedFileContainer;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskFileRange; import org.sleuthkit.datamodel.TskFileRange;
import org.w3c.dom.Document; import org.w3c.dom.Document;
@ -70,24 +73,24 @@ class PhotoRecCarverOutputParser {
* @throws FileNotFoundException * @throws FileNotFoundException
* @throws IOException * @throws IOException
*/ */
List<LayoutFile> parse(File xmlInputFile, long id, AbstractFile af) throws FileNotFoundException, IOException { List<LayoutFile> parse(File xmlInputFile, AbstractFile af, IngestJobContext context) throws FileNotFoundException, IOException {
try { try {
final Document doc = XMLUtil.loadDoc(PhotoRecCarverOutputParser.class, xmlInputFile.toString()); final Document doc = XMLUtil.loadDoc(PhotoRecCarverOutputParser.class, xmlInputFile.toString());
if (doc == null) { if (doc == null) {
return null; return new ArrayList<>();
} }
Element root = doc.getDocumentElement(); Element root = doc.getDocumentElement();
if (root == null) { if (root == null) {
logger.log(Level.SEVERE, "Error loading config file: invalid file format (bad root)."); //NON-NLS logger.log(Level.SEVERE, "Error loading config file: invalid file format (bad root)."); //NON-NLS
return null; return new ArrayList<>();
} }
NodeList fileObjects = root.getElementsByTagName("fileobject"); //NON-NLS NodeList fileObjects = root.getElementsByTagName("fileobject"); //NON-NLS
final int numberOfFiles = fileObjects.getLength(); final int numberOfFiles = fileObjects.getLength();
if (numberOfFiles == 0) { if (numberOfFiles == 0) {
return null; return new ArrayList<>();
} }
String fileName; String fileName;
Long fileSize; Long fileSize;
@ -99,9 +102,14 @@ class PhotoRecCarverOutputParser {
FileManager fileManager = Case.getCurrentCase().getServices().getFileManager(); FileManager fileManager = Case.getCurrentCase().getServices().getFileManager();
// create and initialize the list to put into the database // create and initialize the list to put into the database
List<CarvedFileContainer> carvedFileContainer = new ArrayList<>(); List<CarvingResult.CarvedFile> carvedFiles = new ArrayList<>();
for (int fileIndex = 0; fileIndex < numberOfFiles; ++fileIndex) { for (int fileIndex = 0; fileIndex < numberOfFiles; ++fileIndex) {
if (context.fileIngestIsCancelled() == true) {
// if it was cancelled by the user, result is OK
logger.log(Level.INFO, "PhotoRec cancelled by user"); // NON-NLS
MessageNotifyUtil.Notify.info(PhotoRecCarverIngestModuleFactory.getModuleName(), NbBundle.getMessage(PhotoRecCarverFileIngestModule.class, "PhotoRecIngestModule.cancelledByUser"));
break;
}
entry = (Element) fileObjects.item(fileIndex); entry = (Element) fileObjects.item(fileIndex);
fileNames = entry.getElementsByTagName("filename"); //NON-NLS fileNames = entry.getElementsByTagName("filename"); //NON-NLS
fileSizes = entry.getElementsByTagName("filesize"); //NON-NLS fileSizes = entry.getElementsByTagName("filesize"); //NON-NLS
@ -133,7 +141,7 @@ class PhotoRecCarverOutputParser {
if (fileByteEnd > af.getSize()) { if (fileByteEnd > af.getSize()) {
long overshoot = fileByteEnd - af.getSize(); long overshoot = fileByteEnd - af.getSize();
if (fileSize > overshoot) { if (fileSize > overshoot) {
fileSize = fileSize - overshoot; fileSize -= overshoot;
} else { } else {
// This better never happen... Data for this file is corrupted. Skip it. // This better never happen... Data for this file is corrupted. Skip it.
continue; continue;
@ -144,10 +152,10 @@ class PhotoRecCarverOutputParser {
} }
if (!tskRanges.isEmpty()) { if (!tskRanges.isEmpty()) {
carvedFileContainer.add(new CarvedFileContainer(fileName, fileSize, id, tskRanges)); carvedFiles.add(new CarvingResult.CarvedFile(fileName, fileSize, tskRanges));
} }
} }
return fileManager.addCarvedFiles(carvedFileContainer); return fileManager.addCarvedFiles(new CarvingResult(af, carvedFiles));
} catch (NumberFormatException | TskCoreException ex) { } catch (NumberFormatException | TskCoreException ex) {
logger.log(Level.SEVERE, "Error parsing PhotoRec output and inserting it into the database: {0}", ex); //NON-NLS logger.log(Level.SEVERE, "Error parsing PhotoRec output and inserting it into the database: {0}", ex); //NON-NLS
} }

View File

@ -6,7 +6,7 @@ STIXReportModuleConfigPanel.jLabel2.text=Select a STIX file or directory of STIX
STIXReportModuleConfigPanel.jTextField1.text= STIXReportModuleConfigPanel.jTextField1.text=
STIXReportModuleConfigPanel.jButton1.text=Choose file STIXReportModuleConfigPanel.jButton1.text=Choose file
STIXReportModuleConfigPanel.jCheckBox1.text=Include results for false indicators in output file STIXReportModuleConfigPanel.jCheckBox1.text=Include results for false indicators in output file
STIXReportModule.notifyMsg.unableToOpenReportFile=Unable to open STIX report file {0} STIXReportModule.notifyMsg.unableToOpenReportFile=Unable to complete STIX report.
STIXReportModule.progress.completedWithErrors=Completed with errors STIXReportModule.progress.completedWithErrors=Completed with errors
STIXReportModule.notifyMsg.unableToOpenFileDir=Unable to open STIX file/directory {0} STIXReportModule.notifyMsg.unableToOpenFileDir=Unable to open STIX file/directory {0}
STIXReportModule.progress.couldNotOpenFileDir=Could not open file/directory {0} STIXReportModule.progress.couldNotOpenFileDir=Could not open file/directory {0}

View File

@ -1,14 +1,13 @@
OpenIDE-Module-Name=stix\u30E2\u30B8\u30E5\u30FC\u30EB OpenIDE-Module-Name=stix\u30e2\u30b8\u30e5\u30fc\u30eb
STIXReportModule.getDesc.text=\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u306B\u5BFE\u3057\u3066\u5E7E\u3064\u304B\u306ESTIX\uFF08Structured Threat Information eXpression\uFF1B\u8105\u5A01\u60C5\u5831\u69CB\u9020\u5316\u8A18\u8FF0\u5F62\u5F0F\uFF09\u30D5\u30A1\u30A4\u30EB\u3092\u5B9F\u884C\u3057\u3001\u30EC\u30DD\u30FC\u30C8\u3092\u751F\u6210\u3057\u307E\u3059\u3002\u307E\u305F\u3001\u7591\u308F\u3057\u3044\u30D5\u30A1\u30A4\u30EB\u5185\u306B\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u3092\u4F5C\u6210\u3002 STIXReportModule.getDesc.text=\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u306b\u5bfe\u3057\u3066\u5e7e\u3064\u304b\u306eSTIX\uff08Structured Threat Information eXpression\uff1b\u8105\u5a01\u60c5\u5831\u69cb\u9020\u5316\u8a18\u8ff0\u5f62\u5f0f\uff09\u30d5\u30a1\u30a4\u30eb\u3092\u5b9f\u884c\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u3092\u751f\u6210\u3057\u307e\u3059\u3002\u307e\u305f\u3001\u7591\u308f\u3057\u3044\u30d5\u30a1\u30a4\u30eb\u5185\u306b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u4f5c\u6210\u3002
STIXReportModule.getName.text=STIX STIXReportModule.getName.text=STIX
STIXReportModule.notifyMsg.tooManyArtifactsgt1000="{0}"\u7528\u306B\u751F\u6210\u3055\u308C\u305FSTIX\u95A2\u9023\u306E\u30A2\u30FC\u30C6\u30A3\u30D5\u30A1\u30AF\u30C8\u304C\u591A\u3059\u304E\u307E\u3059\u3002\u6700\u521D\u306E1000\u306E\u307F\u4FDD\u5B58\u3055\u308C\u307E\u3059\u3002 STIXReportModule.notifyMsg.tooManyArtifactsgt1000="{0}"\u7528\u306b\u751f\u6210\u3055\u308c\u305fSTIX\u95a2\u9023\u306e\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u304c\u591a\u3059\u304e\u307e\u3059\u3002\u6700\u521d\u306e1000\u306e\u307f\u4fdd\u5b58\u3055\u308c\u307e\u3059\u3002
STIXReportModule.notifyMsg.unableToOpenFileDir=STIX\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F STIXReportModule.notifyMsg.unableToOpenFileDir=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
STIXReportModule.notifyMsg.unableToOpenReportFile=STIX\u30EC\u30DD\u30FC\u30C8\u30D5\u30A1\u30A4\u30EB{0}\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F STIXReportModule.progress.completedWithErrors=\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u304c\u3001\u5b8c\u4e86\u3057\u307e\u3057\u305f
STIXReportModule.progress.completedWithErrors=\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u304C\u3001\u5B8C\u4E86\u3057\u307E\u3057\u305F STIXReportModule.progress.couldNotOpenFileDir=\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{0}\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
STIXReportModule.progress.couldNotOpenFileDir=\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{0}\u3092\u958B\u3051\u307E\u305B\u3093\u3067\u3057\u305F STIXReportModule.progress.readSTIX=STIX\u30d5\u30a1\u30a4\u30eb\u3092\u30d1\u30fc\u30b9\u4e2d
STIXReportModule.progress.readSTIX=STIX\u30D5\u30A1\u30A4\u30EB\u3092\u30D1\u30FC\u30B9\u4E2D STIXReportModuleConfigPanel.jButton1.text=\u30d5\u30a1\u30a4\u30eb\u3092\u9078\u629e
STIXReportModuleConfigPanel.jButton1.text=\u30D5\u30A1\u30A4\u30EB\u3092\u9078\u629E STIXReportModuleConfigPanel.jCheckBox1.text=\u30a2\u30a6\u30c8\u30d7\u30c3\u30c8\u30d5\u30a1\u30a4\u30eb\u306e\u8aa4\u3063\u305f\u30a4\u30f3\u30b8\u30b1\u30fc\u30bf\u30fc\u306e\u7d50\u679c\u3082\u542b\u3080
STIXReportModuleConfigPanel.jCheckBox1.text=\u30A2\u30A6\u30C8\u30D7\u30C3\u30C8\u30D5\u30A1\u30A4\u30EB\u306E\u8AA4\u3063\u305F\u30A4\u30F3\u30B8\u30B1\u30FC\u30BF\u30FC\u306E\u7D50\u679C\u3082\u542B\u3080 STIXReportModuleConfigPanel.jLabel2.text=STIX\u30d5\u30a1\u30a4\u30eb\u307e\u305f\u306fSTIX\u30d5\u30a1\u30a4\u30eb\u306e\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u9078\u629e
STIXReportModuleConfigPanel.jLabel2.text=STIX\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306FSTIX\u30D5\u30A1\u30A4\u30EB\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u9078\u629E STIXReportModule.notifyErr.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093
STIXReportModule.notifyErr.noFildDirProvided=STIX\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093 STIXReportModule.progress.noFildDirProvided=STIX\u30d5\u30a1\u30a4\u30eb\uff0f\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u304c\u63d0\u4f9b\u3055\u308c\u3066\u3044\u307e\u305b\u3093
STIXReportModule.progress.noFildDirProvided=STIX\u30D5\u30A1\u30A4\u30EB\uFF0F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u63D0\u4F9B\u3055\u308C\u3066\u3044\u307E\u305B\u3093

View File

@ -18,48 +18,47 @@
*/ */
package org.sleuthkit.autopsy.modules.stix; package org.sleuthkit.autopsy.modules.stix;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.logging.Level;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.JPanel; import javax.swing.JPanel;
import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller; import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName; import javax.xml.namespace.QName;
import org.mitre.cybox.cybox_2.ObjectType; import org.mitre.cybox.cybox_2.ObjectType;
import org.mitre.cybox.cybox_2.Observable; import org.mitre.cybox.cybox_2.Observable;
import org.mitre.cybox.cybox_2.ObservableCompositionType; import org.mitre.cybox.cybox_2.ObservableCompositionType;
import org.mitre.cybox.cybox_2.OperatorTypeEnum;
import org.mitre.cybox.objects.AccountObjectType;
import org.mitre.cybox.objects.Address;
import org.mitre.cybox.objects.DomainName;
import org.mitre.cybox.objects.EmailMessage;
import org.mitre.cybox.objects.FileObjectType;
import org.mitre.cybox.objects.SystemObjectType;
import org.mitre.cybox.objects.URIObjectType;
import org.mitre.cybox.objects.URLHistory;
import org.mitre.cybox.objects.WindowsNetworkShare;
import org.mitre.cybox.objects.WindowsRegistryKey;
import org.mitre.stix.common_1.IndicatorBaseType; import org.mitre.stix.common_1.IndicatorBaseType;
import org.mitre.stix.indicator_2.Indicator; import org.mitre.stix.indicator_2.Indicator;
import org.mitre.stix.stix_1.STIXPackage; import org.mitre.stix.stix_1.STIXPackage;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.report.GeneralReportModule;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.report.ReportProgressPanel; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.mitre.cybox.cybox_2.OperatorTypeEnum;
import org.mitre.cybox.objects.Address;
import org.mitre.cybox.objects.FileObjectType;
import org.mitre.cybox.objects.URIObjectType;
import org.mitre.cybox.objects.EmailMessage;
import org.mitre.cybox.objects.WindowsNetworkShare;
import org.mitre.cybox.objects.AccountObjectType;
import org.mitre.cybox.objects.SystemObjectType;
import org.mitre.cybox.objects.URLHistory;
import org.mitre.cybox.objects.DomainName;
import org.mitre.cybox.objects.WindowsRegistryKey;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.report.GeneralReportModule;
import org.sleuthkit.autopsy.report.ReportProgressPanel;
import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus;
import org.sleuthkit.datamodel.TskCoreException;
/** /**
* *
@ -79,8 +78,6 @@ public class STIXReportModule implements GeneralReportModule {
private final boolean skipShortCircuit = true; private final boolean skipShortCircuit = true;
private BufferedWriter output = null;
// Hidden constructor for the report // Hidden constructor for the report
private STIXReportModule() { private STIXReportModule() {
} }
@ -100,38 +97,23 @@ public class STIXReportModule implements GeneralReportModule {
* @param progressPanel panel to update the report's progress * @param progressPanel panel to update the report's progress
*/ */
@Override @Override
@Messages({"STIXReportModule.srcModuleName.text=STIX Report"})
public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) { public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
// Start the progress bar and setup the report // Start the progress bar and setup the report
progressPanel.setIndeterminate(false); progressPanel.setIndeterminate(false);
progressPanel.start(); progressPanel.start();
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX")); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.readSTIX"));
reportPath = baseReportDir + getRelativeFilePath(); reportPath = baseReportDir + getRelativeFilePath();
File reportFile = new File(reportPath);
// Check if the user wants to display all output or just hits // Check if the user wants to display all output or just hits
reportAllResults = configPanel.getShowAllResults(); reportAllResults = configPanel.getShowAllResults();
// Set up the output file
try {
File file = new File(reportPath);
output = new BufferedWriter(new FileWriter(file));
} catch (IOException ex) {
logger.log(Level.SEVERE, String.format("Unable to open STIX report file %s", reportPath), ex); //NON-NLS
MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
NbBundle.getMessage(this.getClass(),
"STIXReportModule.notifyMsg.unableToOpenReportFile",
reportPath),
MessageNotifyUtil.MessageType.ERROR);
progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
return;
}
// Keep track of whether any errors occur during processing // Keep track of whether any errors occur during processing
boolean hadErrors = false; boolean hadErrors = false;
// Process the file/directory name entry // Process the file/directory name entry
String stixFileName = configPanel.getStixFile(); String stixFileName = configPanel.getStixFile();
if (stixFileName == null) { if (stixFileName == null) {
logger.log(Level.SEVERE, "STIXReportModuleConfigPanel.stixFile not initialized "); //NON-NLS logger.log(Level.SEVERE, "STIXReportModuleConfigPanel.stixFile not initialized "); //NON-NLS
MessageNotifyUtil.Message.error( MessageNotifyUtil.Message.error(
@ -139,6 +121,7 @@ public class STIXReportModule implements GeneralReportModule {
progressPanel.complete(ReportStatus.ERROR); progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel( progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided")); NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided"));
new File(baseReportDir).delete();
return; return;
} }
if (stixFileName.isEmpty()) { if (stixFileName.isEmpty()) {
@ -148,6 +131,7 @@ public class STIXReportModule implements GeneralReportModule {
progressPanel.complete(ReportStatus.ERROR); progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel( progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided")); NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.noFildDirProvided"));
new File(baseReportDir).delete();
return; return;
} }
File stixFile = new File(stixFileName); File stixFile = new File(stixFileName);
@ -160,58 +144,66 @@ public class STIXReportModule implements GeneralReportModule {
progressPanel.complete(ReportStatus.ERROR); progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel( progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.couldNotOpenFileDir", stixFileName)); NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.couldNotOpenFileDir", stixFileName));
new File(baseReportDir).delete();
return; return;
} }
// Store the path try (BufferedWriter output = new BufferedWriter(new FileWriter(reportFile))) {
ModuleSettings.setConfigSetting("STIX", "defaultPath", stixFileName); //NON-NLS // Store the path
ModuleSettings.setConfigSetting("STIX", "defaultPath", stixFileName); //NON-NLS
// Create array of stix file(s) // Create array of stix file(s)
File[] stixFiles; File[] stixFiles;
if (stixFile.isFile()) { if (stixFile.isFile()) {
stixFiles = new File[1]; stixFiles = new File[1];
stixFiles[0] = stixFile; stixFiles[0] = stixFile;
} else { } else {
stixFiles = stixFile.listFiles(); stixFiles = stixFile.listFiles();
}
// Set the length of the progress bar - we increment twice for each file
progressPanel.setMaximumProgress(stixFiles.length * 2 + 1);
// Process each STIX file
for (File file : stixFiles) {
try {
processFile(file.getAbsolutePath(), progressPanel);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Unable to process STIX file %s", file), ex); //NON-NLS
MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
ex.getLocalizedMessage(),
MessageNotifyUtil.MessageType.ERROR);
hadErrors = true;
} }
// Clear out the ID maps before loading the next file // Set the length of the progress bar - we increment twice for each file
idToObjectMap = new HashMap<String, ObjectType>(); progressPanel.setMaximumProgress(stixFiles.length * 2 + 1);
idToResult = new HashMap<String, ObservableResult>();
}
// Close the output file // Process each STIX file
if (output != null) { for (File file : stixFiles) {
try { if (progressPanel.getStatus() == ReportStatus.CANCELED) {
output.close(); return;
} catch (IOException ex) { }
logger.log(Level.SEVERE, String.format("Error closing STIX report file %s", reportPath), ex); //NON-NLS try {
processFile(file.getAbsolutePath(), progressPanel, output);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Unable to process STIX file %s", file), ex); //NON-NLS
MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
ex.getLocalizedMessage(),
MessageNotifyUtil.MessageType.ERROR);
hadErrors = true;
}
// Clear out the ID maps before loading the next file
idToObjectMap = new HashMap<String, ObjectType>();
idToResult = new HashMap<String, ObservableResult>();
} }
}
// Set the progress bar to done. If any errors occurred along the way, modify // Set the progress bar to done. If any errors occurred along the way, modify
// the "complete" message to indicate this. // the "complete" message to indicate this.
if (hadErrors) { Case.getCurrentCase().addReport(reportPath, Bundle.STIXReportModule_srcModuleName_text(), "");
if (hadErrors) {
progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
} else {
progressPanel.complete(ReportStatus.COMPLETE);
}
} catch (IOException ex) {
logger.log(Level.SEVERE, "Unable to complete STIX report.", ex); //NON-NLS
MessageNotifyUtil.Notify.show("STIXReportModule", //NON-NLS
NbBundle.getMessage(this.getClass(),
"STIXReportModule.notifyMsg.unableToOpenReportFile"),
MessageNotifyUtil.MessageType.ERROR);
progressPanel.complete(ReportStatus.ERROR); progressPanel.complete(ReportStatus.ERROR);
progressPanel.updateStatusLabel( progressPanel.updateStatusLabel(
NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors")); NbBundle.getMessage(this.getClass(), "STIXReportModule.progress.completedWithErrors"));
} else { } catch (TskCoreException ex) {
progressPanel.complete(ReportStatus.COMPLETE); logger.log(Level.SEVERE, "Unable to add report to database.", ex);
} }
} }
@ -223,14 +215,14 @@ public class STIXReportModule implements GeneralReportModule {
* *
* @throws TskCoreException * @throws TskCoreException
*/ */
private void processFile(String stixFile, ReportProgressPanel progressPanel) throws private void processFile(String stixFile, ReportProgressPanel progressPanel, BufferedWriter output) throws
TskCoreException { TskCoreException {
// Load the STIX file // Load the STIX file
STIXPackage stix; STIXPackage stix;
stix = loadSTIXFile(stixFile); stix = loadSTIXFile(stixFile);
printFileHeader(stixFile); printFileHeader(stixFile, output);
// Save any observables listed up front // Save any observables listed up front
processObservables(stix); processObservables(stix);
@ -240,7 +232,7 @@ public class STIXReportModule implements GeneralReportModule {
registryFileData = EvalRegistryObj.copyRegistryFiles(); registryFileData = EvalRegistryObj.copyRegistryFiles();
// Process the indicators // Process the indicators
processIndicators(stix); processIndicators(stix, output);
progressPanel.increment(); progressPanel.increment();
} }
@ -292,7 +284,7 @@ public class STIXReportModule implements GeneralReportModule {
* *
* @param stix STIXPackage * @param stix STIXPackage
*/ */
private void processIndicators(STIXPackage stix) throws TskCoreException { private void processIndicators(STIXPackage stix, BufferedWriter output) throws TskCoreException {
if (stix.getIndicators() != null) { if (stix.getIndicators() != null) {
List<IndicatorBaseType> s = stix.getIndicators().getIndicators(); List<IndicatorBaseType> s = stix.getIndicators().getIndicators();
for (IndicatorBaseType t : s) { for (IndicatorBaseType t : s) {
@ -302,7 +294,7 @@ public class STIXReportModule implements GeneralReportModule {
if (ind.getObservable().getObject() != null) { if (ind.getObservable().getObject() != null) {
ObservableResult result = evaluateSingleObservable(ind.getObservable(), ""); ObservableResult result = evaluateSingleObservable(ind.getObservable(), "");
if (result.isTrue() || reportAllResults) { if (result.isTrue() || reportAllResults) {
writeResultsToFile(ind, result.getDescription(), result.isTrue()); writeResultsToFile(ind, result.getDescription(), result.isTrue(), output);
} }
if (result.isTrue()) { if (result.isTrue()) {
saveResultsAsArtifacts(ind, result); saveResultsAsArtifacts(ind, result);
@ -311,7 +303,7 @@ public class STIXReportModule implements GeneralReportModule {
ObservableResult result = evaluateObservableComposition(ind.getObservable().getObservableComposition(), " "); ObservableResult result = evaluateObservableComposition(ind.getObservable().getObservableComposition(), " ");
if (result.isTrue() || reportAllResults) { if (result.isTrue() || reportAllResults) {
writeResultsToFile(ind, result.getDescription(), result.isTrue()); writeResultsToFile(ind, result.getDescription(), result.isTrue(), output);
} }
if (result.isTrue()) { if (result.isTrue()) {
saveResultsAsArtifacts(ind, result); saveResultsAsArtifacts(ind, result);
@ -376,7 +368,7 @@ public class STIXReportModule implements GeneralReportModule {
* @param resultStr - Full results for this indicator * @param resultStr - Full results for this indicator
* @param found - true if the indicator was found in datasource(s) * @param found - true if the indicator was found in datasource(s)
*/ */
private void writeResultsToFile(Indicator ind, String resultStr, boolean found) { private void writeResultsToFile(Indicator ind, String resultStr, boolean found, BufferedWriter output) {
if (output != null) { if (output != null) {
try { try {
if (found) { if (found) {
@ -412,7 +404,7 @@ public class STIXReportModule implements GeneralReportModule {
* *
* @param a_fileName * @param a_fileName
*/ */
private void printFileHeader(String a_fileName) { private void printFileHeader(String a_fileName, BufferedWriter output) {
if (output != null) { if (output != null) {
try { try {
char[] chars = new char[a_fileName.length() + 8]; char[] chars = new char[a_fileName.length() + 8];

View File

@ -19,7 +19,7 @@
package org.sleuthkit.autopsy.modules.stix; package org.sleuthkit.autopsy.modules.stix;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard; import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -58,6 +58,7 @@ class StixArtifactData {
objType = a_objType; objType = a_objType;
} }
@Messages({"StixArtifactData.indexError.message=Failed to index STIX interesting file hit artifact for keyword search."})
public void createArtifact(String a_title) throws TskCoreException { public void createArtifact(String a_title) throws TskCoreException {
Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard(); Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
@ -72,14 +73,13 @@ class StixArtifactData {
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Stix", setName)); //NON-NLS bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Stix", setName)); //NON-NLS
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE, "Stix", observableId)); //NON-NLS bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TITLE, "Stix", observableId)); //NON-NLS
bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, "Stix", objType)); //NON-NLS bba.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, "Stix", objType)); //NON-NLS
try { try {
// index the artifact for keyword search // index the artifact for keyword search
blackboard.indexArtifact(bba); blackboard.indexArtifact(bba);
} catch (Blackboard.BlackboardException ex) { } catch (Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.error.msg", bba.getDisplayName()), ex); //NON-NLS logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS
MessageNotifyUtil.Notify.error( MessageNotifyUtil.Notify.error(Bundle.StixArtifactData_indexError_message(), bba.getDisplayName());
NbBundle.getMessage(Blackboard.class, "Blackboard.unableToIndexArtifact.exception.msg"), bba.getDisplayName());
} }
} }

View File

@ -179,7 +179,7 @@ ReportHTML.addThumbRows.dataType.msg=Tagged Results and Contents that contain im
ReportHTML.thumbLink.tags=Tags\: ReportHTML.thumbLink.tags=Tags\:
ReportHTML.getName.text=Results - HTML ReportHTML.getName.text=Results - HTML
ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.getDesc.text=A report about results and tagged items in HTML format.
ReportHTML.writeIndex.title=Autopsy Report for case {0} ReportHTML.writeIndex.title=for case {0}
ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup.
ReportHTML.writeIndex.noFrames.seeNav=Please see <a href\="nav.html">the navigation page</a> for artifact links, ReportHTML.writeIndex.noFrames.seeNav=Please see <a href\="nav.html">the navigation page</a> for artifact links,
ReportHTML.writeIndex.seeSum=and <a href\="summary.html">the summary page</a> for a case summary. ReportHTML.writeIndex.seeSum=and <a href\="summary.html">the summary page</a> for a case summary.
@ -225,7 +225,8 @@ ReportHTML.writeSum.noCaseNum=<i>No case number</i>
ReportBodyFile.generateReport.srcModuleName.text=TSK Body File ReportBodyFile.generateReport.srcModuleName.text=TSK Body File
ReportExcel.endReport.srcModuleName.text=Excel Report ReportExcel.endReport.srcModuleName.text=Excel Report
ReportHTML.writeIndex.srcModuleName.text=HTML Report ReportHTML.writeIndex.srcModuleName.text=HTML Report
ReportKML.genReport.srcModuleName.text=KML Report ReportKML.genReport.srcModuleName.text=Geospatial Data
ReportKML.genReport.reportName=KML Report
ReportGenerator.artTableColHdr.extension.text=Extension ReportGenerator.artTableColHdr.extension.text=Extension
ReportGenerator.artTableColHdr.mimeType.text=MIME Type ReportGenerator.artTableColHdr.mimeType.text=MIME Type
ReportGenerator.artTableColHdr.processorArchitecture.text=Processor Architecture ReportGenerator.artTableColHdr.processorArchitecture.text=Processor Architecture

View File

@ -188,7 +188,7 @@ ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50 ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50
ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7 ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7
ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8 ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8
ReportKML.genReport.srcModuleName.text=KML\u30ec\u30dd\u30fc\u30c8 ReportKML.genReport.reportName=KML\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u4fc2\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8 ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u4fc2\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8
ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8 ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8
ReportGenerator.artTableColHdr.devMake=\u6a5f\u5668\u578b\u540d ReportGenerator.artTableColHdr.devMake=\u6a5f\u5668\u578b\u540d

File diff suppressed because it is too large Load Diff

View File

@ -838,10 +838,17 @@ class ReportHTML implements TableReportModule {
try { try {
indexOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(indexFilePath), "UTF-8")); //NON-NLS indexOut = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(indexFilePath), "UTF-8")); //NON-NLS
StringBuilder index = new StringBuilder(); StringBuilder index = new StringBuilder();
index.append("<head>\n<title>").append( //NON-NLS final String reportTitle = reportBranding.getReportTitle();
String iconPath = reportBranding.getAgencyLogoPath();
if (iconPath == null){
// use default Autopsy icon if custom icon is not set
iconPath = "favicon.ico";
}
index.append("<head>\n<title>").append(reportTitle).append(" ").append(
NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append( NbBundle.getMessage(this.getClass(), "ReportHTML.writeIndex.title", currentCase.getName())).append(
"</title>\n"); //NON-NLS "</title>\n"); //NON-NLS
index.append("<link rel=\"icon\" type=\"image/ico\" href=\"favicon.ico\" />\n"); //NON-NLS index.append("<link rel=\"icon\" type=\"image/ico\" href=\"")
.append(iconPath).append("\" />\n"); //NON-NLS
index.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); //NON-NLS index.append("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"); //NON-NLS
index.append("</head>\n"); //NON-NLS index.append("</head>\n"); //NON-NLS
index.append("<frameset cols=\"350px,*\">\n"); //NON-NLS index.append("<frameset cols=\"350px,*\">\n"); //NON-NLS

1016
Core/src/org/sleuthkit/autopsy/report/ReportKML.java Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -24,9 +24,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import static java.util.Collections.swap; import static java.util.Collections.swap;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JList; import javax.swing.JList;
import javax.swing.JPanel; import javax.swing.JPanel;
@ -137,8 +135,8 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
// Make sure that the report module has a valid non-null name. // Make sure that the report module has a valid non-null name.
private boolean moduleIsValid(ReportModule module) { private boolean moduleIsValid(ReportModule module) {
return module.getName() != null && !module.getName().isEmpty() return module.getName() != null && !module.getName().isEmpty()
&& module.getRelativeFilePath() != null; && module.getRelativeFilePath() != null;
} }
private void popupWarning(ReportModule module) { private void popupWarning(ReportModule module) {
@ -163,13 +161,12 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
* *
* @return * @return
*/ */
Map<TableReportModule, Boolean> getTableModuleStates() { TableReportModule getTableModule() {
Map<TableReportModule, Boolean> reportModuleStates = new LinkedHashMap<>();
ReportModule mod = getSelectedModule(); ReportModule mod = getSelectedModule();
if (tableModules.contains(mod)) { if (tableModules.contains(mod)) {
reportModuleStates.put((TableReportModule) mod, Boolean.TRUE); return (TableReportModule) mod;
} }
return reportModuleStates; return null;
} }
/** /**
@ -177,13 +174,12 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
* *
* @return * @return
*/ */
Map<GeneralReportModule, Boolean> getGeneralModuleStates() { GeneralReportModule getGeneralModule() {
Map<GeneralReportModule, Boolean> reportModuleStates = new LinkedHashMap<>();
ReportModule mod = getSelectedModule(); ReportModule mod = getSelectedModule();
if (generalModules.contains(mod)) { if (generalModules.contains(mod)) {
reportModuleStates.put((GeneralReportModule) mod, Boolean.TRUE); return (GeneralReportModule) mod;
} }
return reportModuleStates; return null;
} }
/** /**
@ -191,13 +187,12 @@ final class ReportVisualPanel1 extends JPanel implements ListSelectionListener {
* *
* @return * @return
*/ */
Map<FileReportModule, Boolean> getFileModuleStates() { FileReportModule getFileModule() {
Map<FileReportModule, Boolean> reportModuleStates = new LinkedHashMap<>();
ReportModule mod = getSelectedModule(); ReportModule mod = getSelectedModule();
if (fileModules.contains(mod)) { if (fileModules.contains(mod)) {
reportModuleStates.put((FileReportModule) mod, Boolean.TRUE); return (FileReportModule) mod;
} }
return reportModuleStates; return null;
} }
/** /**

View File

@ -1,4 +1,4 @@
/* /*
* *
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
@ -65,13 +65,17 @@ public final class ReportWizardAction extends CallableSystemAction implements Pr
wiz.setTitle(NbBundle.getMessage(ReportWizardAction.class, "ReportWizardAction.reportWiz.title")); wiz.setTitle(NbBundle.getMessage(ReportWizardAction.class, "ReportWizardAction.reportWiz.title"));
if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) { if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
ReportGenerator generator = new ReportGenerator((Map<TableReportModule, Boolean>) wiz.getProperty("tableModuleStates"), //NON-NLS ReportGenerator generator = new ReportGenerator(); //NON-NLS
(Map<GeneralReportModule, Boolean>) wiz.getProperty("generalModuleStates"), //NON-NLS TableReportModule tableReport = (TableReportModule) wiz.getProperty("tableModule");
(Map<FileReportModule, Boolean>) wiz.getProperty("fileModuleStates")); //NON-NLS GeneralReportModule generalReport = (GeneralReportModule) wiz.getProperty("generalModule");
generator.generateTableReports((Map<BlackboardArtifact.Type, Boolean>) wiz.getProperty("artifactStates"), (Map<String, Boolean>) wiz.getProperty("tagStates")); //NON-NLS FileReportModule fileReport = (FileReportModule) wiz.getProperty("fileModule");
generator.generateFileListReports((Map<FileReportDataTypes, Boolean>) wiz.getProperty("fileReportOptions")); //NON-NLS if (tableReport != null) {
generator.generateGeneralReports(); generator.generateTableReport(tableReport, (Map<BlackboardArtifact.Type, Boolean>) wiz.getProperty("artifactStates"), (Map<String, Boolean>) wiz.getProperty("tagStates")); //NON-NLS
generator.displayProgressPanels(); } else if (generalReport != null) {
generator.generateGeneralReport(generalReport);
} else if (fileReport != null) {
generator.generateFileListReport(fileReport, (Map<FileReportDataTypes, Boolean>) wiz.getProperty("fileReportOptions")); //NON-NLS
}
} }
} }

View File

@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.report;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.Collection; import java.util.Collection;
import java.util.Map;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import javax.swing.JButton; import javax.swing.JButton;
import javax.swing.event.ChangeListener; import javax.swing.event.ChangeListener;
@ -108,17 +107,17 @@ class ReportWizardPanel1 implements WizardDescriptor.FinishablePanel<WizardDescr
@Override @Override
public void storeSettings(WizardDescriptor wiz) { public void storeSettings(WizardDescriptor wiz) {
Map<TableReportModule, Boolean> tables = getComponent().getTableModuleStates(); TableReportModule module = getComponent().getTableModule();
Map<GeneralReportModule, Boolean> generals = getComponent().getGeneralModuleStates(); GeneralReportModule general = getComponent().getGeneralModule();
wiz.putProperty("tableModuleStates", tables); //NON-NLS wiz.putProperty("tableModule", module); //NON-NLS
wiz.putProperty("generalModuleStates", generals); //NON-NLS wiz.putProperty("generalModule", general); //NON-NLS
wiz.putProperty("fileModuleStates", getComponent().getFileModuleStates()); //NON-NLS wiz.putProperty("fileModule", getComponent().getFileModule()); //NON-NLS
// Store preferences that WizardIterator will use to determine what // Store preferences that WizardIterator will use to determine what
// panels need to be shown // panels need to be shown
Preferences prefs = NbPreferences.forModule(ReportWizardPanel1.class); Preferences prefs = NbPreferences.forModule(ReportWizardPanel1.class);
prefs.putBoolean("tableModule", any(tables.values())); //NON-NLS prefs.putBoolean("tableModule", module != null); //NON-NLS
prefs.putBoolean("generalModule", any(generals.values())); //NON-NLS prefs.putBoolean("generalModule", general != null); //NON-NLS
} }
/** /**

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2">
<Document>
<StyleMap id="yellowFeature">
<Pair>
<key>normal</key>
<styleUrl>#n_YellowPushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#h_YellowPushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="n_YellowPushpin">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>0</scale>
</LabelStyle>
<LineStyle>
<color>FF00FFFF</color>
<width>5.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<Style id="h_YellowPushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FF00FFFF</color>
<width>10.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<StyleMap id="blueFeature">
<Pair>
<key>normal</key>
<styleUrl>#n_bluePushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#h_bluePushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="n_bluePushpin">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>0</scale>
</LabelStyle>
<LineStyle>
<color>FFE63900</color>
<width>5.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<Style id="h_bluePushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FFE63900</color>
<width>10.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<StyleMap id="redFeature">
<Pair>
<key>normal</key>
<styleUrl>#n_redPushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#h_redPushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="n_redPushpin">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>0</scale>
</LabelStyle>
<LineStyle>
<color>FF0000FF</color>
<width>5.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<Style id="h_redPushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FF0000FF</color>
<width>10.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<StyleMap id="greenFeature">
<Pair>
<key>normal</key>
<styleUrl>#n_greenPushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#h_greenPushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="n_greenPushpin">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FF00CC00</color>
<width>5.0</width>
</LineStyle>
<BalloonStyle>
<text>
A route was planned between these two points. The green line connecting the points is not the actual route, but it indicates which Start and End points are associated with each other.
$[description]
</text>
</BalloonStyle>
</Style>
<Style id="h_greenPushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FF00CC00</color>
<width>10.0</width>
</LineStyle>
<BalloonStyle>
<text>
A route was planned between these two points. The green line connecting the points is not the actual route, but it indicates which Start and End points are associated with each other.
$[description]
</text>
</BalloonStyle>
</Style>
<StyleMap id="purpleFeature">
<Pair>
<key>normal</key>
<styleUrl>#n_purplePushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#h_purplePushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="n_purplePushpin">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/purple-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FFCC0066</color>
<width>5.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<Style id="h_purplePushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/purple-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FFCC0066</color>
<width>10.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
<StyleMap id="whiteFeature">
<Pair>
<key>normal</key>
<styleUrl>#n_whitePushpin</styleUrl>
</Pair>
<Pair>
<key>highlight</key>
<styleUrl>#h_whitePushpin</styleUrl>
</Pair>
</StyleMap>
<Style id="n_whitePushpin">
<IconStyle>
<scale>1.0</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>0</scale>
</LabelStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
<LineStyle>
<color>FFFFFFFF</color>
<width>5.0</width>
</LineStyle>
</Style>
<Style id="h_whitePushpin">
<IconStyle>
<scale>1.3</scale>
<Icon>
<href>http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png</href>
</Icon>
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
</IconStyle>
<LabelStyle>
<scale>1</scale>
</LabelStyle>
<LineStyle>
<color>FFFFFFFF</color>
<width>10.0</width>
</LineStyle>
<BalloonStyle>
<text>$[description]</text>
</BalloonStyle>
</Style>
</Document>
</kml>

View File

@ -9,7 +9,7 @@ Timeline.zoomOutButton.text=Zoom Out
Timeline.goToButton.text=Go To\: Timeline.goToButton.text=Go To\:
Timeline.yearBarChart.x.years=Years Timeline.yearBarChart.x.years=Years
Timeline.resultPanel.loading=Loading... Timeline.resultPanel.loading=Loading...
Timeline.node.root=Root
TimelineFrame.title=Timeline TimelineFrame.title=Timeline
TimelinePanel.jButton1.text=6m TimelinePanel.jButton1.text=6m
TimelinePanel.jButton13.text=all TimelinePanel.jButton13.text=all
@ -24,4 +24,4 @@ TimelinePanel.jButton7.text=3d
TimelinePanel.jButton2.text=1m TimelinePanel.jButton2.text=1m
TimelinePanel.jButton3.text=3m TimelinePanel.jButton3.text=3m
TimelinePanel.jButton4.text=2w TimelinePanel.jButton4.text=2w
ProgressWindow.progressHeader.text=\ ProgressWindow.progressHeader.text=\

View File

@ -1,48 +1,48 @@
CTL_MakeTimeline=\u300C\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u300D CTL_MakeTimeline=\u300c\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u300d
CTL_TimeLineTopComponent=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A6\u30A3\u30F3\u30C9\u30A6 CTL_TimeLineTopComponent=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a6\u30a3\u30f3\u30c9\u30a6
CTL_TimeLineTopComponentAction=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C8\u30C3\u30D7\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8 CTL_TimeLineTopComponentAction=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c8\u30c3\u30d7\u30b3\u30f3\u30dd\u30fc\u30cd\u30f3\u30c8
HINT_TimeLineTopComponent=\u3053\u308C\u306F\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A6\u30A3\u30F3\u30C9\u30A6\u3067\u3059 HINT_TimeLineTopComponent=\u3053\u308c\u306f\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a6\u30a3\u30f3\u30c9\u30a6\u3067\u3059
OpenTimelineAction.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3 OpenTimelineAction.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3
Timeline.frameName.text={0} - Autopsy\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3 Timeline.frameName.text={0} - Autopsy\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3
Timeline.goToButton.text=\u4E0B\u8A18\u3078\u79FB\u52D5\uFF1A Timeline.goToButton.text=\u4e0b\u8a18\u3078\u79fb\u52d5\uff1a
Timeline.node.root=\u30EB\u30FC\u30C8 Timeline.pushDescrLOD.confdlg.msg={0}\u30a4\u30d9\u30f3\u30c8\u306e\u8a73\u7d30\u304c\u8868\u793a\u53ef\u80fd\u3067\u3059\u3002\u3053\u306e\u51e6\u7406\u306f\u9577\u6642\u9593\u304b\u304b\u308b\u3082\u3057\u304f\u306fAutopsy\u3092\u30af\u30e9\u30c3\u30b7\u30e5\u3059\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002\n\n\u5b9f\u884c\u3057\u307e\u3059\u304b\uff1f
Timeline.pushDescrLOD.confdlg.msg={0}\u30A4\u30D9\u30F3\u30C8\u306E\u8A73\u7D30\u304C\u8868\u793A\u53EF\u80FD\u3067\u3059\u3002\u3053\u306E\u51E6\u7406\u306F\u9577\u6642\u9593\u304B\u304B\u308B\u3082\u3057\u304F\u306FAutopsy\u3092\u30AF\u30E9\u30C3\u30B7\u30E5\u3059\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n\n\u5B9F\u884C\u3057\u307E\u3059\u304B\uFF1F Timeline.resultPanel.loading=\u30ed\u30fc\u30c9\u4e2d\u30fb\u30fb\u30fb
Timeline.resultPanel.loading=\u30ED\u30FC\u30C9\u4E2D\u30FB\u30FB\u30FB Timeline.resultsPanel.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u7d50\u679c
Timeline.resultsPanel.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u7D50\u679C Timeline.runJavaFxThread.progress.creating=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u4f5c\u6210\u4e2d\u30fb\u30fb\u30fb
Timeline.runJavaFxThread.progress.creating=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u4F5C\u6210\u4E2D\u30FB\u30FB\u30FB Timeline.zoomOutButton.text=\u30ba\u30fc\u30e0\u30a2\u30a6\u30c8
Timeline.zoomOutButton.text=\u30BA\u30FC\u30E0\u30A2\u30A6\u30C8 TimelineFrame.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3
TimelineFrame.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3 TimeLineTopComponent.eventsTab.name=\u30a4\u30d9\u30f3\u30c8
TimeLineTopComponent.eventsTab.name=\u30A4\u30D9\u30F3\u30C8 TimeLineTopComponent.filterTab.name=\u30d5\u30a3\u30eb\u30bf\u30fc
TimeLineTopComponent.filterTab.name=\u30D5\u30A3\u30EB\u30BF\u30FC OpenTimeLineAction.msgdlg.text=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u30c7\u30fc\u30bf\u30bd\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\u3002
OpenTimeLineAction.msgdlg.text=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u3092\u4F5C\u6210\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u30C7\u30FC\u30BF\u30BD\u30FC\u30B9\u304C\u3042\u308A\u307E\u305B\u3093\u3002 PrompDialogManager.buttonType.continueNoUpdate=\u66f4\u65b0\u305b\u305a\u6b21\u3078
PrompDialogManager.buttonType.continueNoUpdate=\u66F4\u65B0\u305B\u305A\u6B21\u3078 PrompDialogManager.buttonType.showTimeline=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u8868\u793a
PrompDialogManager.buttonType.showTimeline=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u3092\u8868\u793A PrompDialogManager.buttonType.update=\u66f4\u65b0
PrompDialogManager.buttonType.update=\u66F4\u65B0 PromptDialogManager.confirmDuringIngest.contentText=\u6b21\u3078\u9032\u307f\u307e\u3059\u304b\uff1f
PromptDialogManager.confirmDuringIngest.contentText=\u6B21\u3078\u9032\u307F\u307E\u3059\u304B\uFF1F PromptDialogManager.confirmDuringIngest.headerText=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u524d\u306b\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u3092\u8868\u793a\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307e\u3059\u3002\n\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u304c\u5b8c\u6210\u3057\u3066\u3044\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
PromptDialogManager.confirmDuringIngest.headerText=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u5B8C\u4E86\u3059\u308B\u524D\u306B\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u3092\u8868\u793A\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059\u3002\n\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u304C\u5B8C\u6210\u3057\u3066\u3044\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 PromptDialogManager.progressDialog.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u3092\u5165\u529b\u4e2d
PromptDialogManager.progressDialog.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C7\u30FC\u30BF\u3092\u5165\u529B\u4E2D PromptDialogManager.rebuildPrompt.details=\u8a73\u7d30\uff1a
PromptDialogManager.rebuildPrompt.details=\u8A73\u7D30\uFF1A PromptDialogManager.rebuildPrompt.headerText=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u304c\u4e0d\u5b8c\u5168\u307e\u305f\u306f\u6700\u65b0\u3067\u306f\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\n \u6b20\u843d\u3057\u3066\u3044\u308b\u307e\u305f\u306f\u4e0d\u6b63\u78ba\u306a\u30a4\u30d9\u30f3\u30c8\u304c\u4e00\u90e8\u3042\u308b\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002\u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u3044\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
PromptDialogManager.rebuildPrompt.headerText=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304C\u4E0D\u5B8C\u5168\u307E\u305F\u306F\u6700\u65B0\u3067\u306F\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002\n \u6B20\u843D\u3057\u3066\u3044\u308B\u307E\u305F\u306F\u4E0D\u6B63\u78BA\u306A\u30A4\u30D9\u30F3\u30C8\u304C\u4E00\u90E8\u3042\u308B\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002\u4E00\u90E8\u306E\u6A5F\u80FD\u304C\u5229\u7528\u3067\u304D\u306A\u3044\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 Timeline.confirmation.dialogs.title=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f
Timeline.confirmation.dialogs.title=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u66F4\u65B0\u3057\u307E\u3059\u304B\uFF1F Timeline.pushDescrLOD.confdlg.title=\u8aac\u660e\u306e\u8a18\u8ff0\u30ec\u30d9\u30eb\u3092\u5909\u66f4\u3057\u307e\u3059\u304b\uff1f
Timeline.pushDescrLOD.confdlg.title=\u8AAC\u660E\u306E\u8A18\u8FF0\u30EC\u30D9\u30EB\u3092\u5909\u66F4\u3057\u307E\u3059\u304B\uFF1F TimeLineController.errorTitle=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a8\u30e9\u30fc
TimeLineController.errorTitle=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A8\u30E9\u30FC TimeLineController.outOfDate.errorMessage=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u304c\u6700\u65b0\u304b\u78ba\u8a8d\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002\u66f4\u65b0\u304c\u5fc5\u8981\u3060\u3068\u60f3\u5b9a\u3057\u307e\u3059\u3002
TimeLineController.outOfDate.errorMessage=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u304C\u6700\u65B0\u304B\u78BA\u8A8D\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002\u66F4\u65B0\u304C\u5FC5\u8981\u3060\u3068\u60F3\u5B9A\u3057\u307E\u3059\u3002 TimeLineController.rebuildReasons.incompleteOldSchema=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a4\u30d9\u30f3\u30c8\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u4e0d\u5b8c\u5168\u306a\u60c5\u5831\u304c\u4ee5\u524d\u5165\u529b\u3055\u308c\u3066\u3044\u307e\u3057\u305f\uff1a\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u66f4\u65b0\u3057\u306a\u3044\u3068\u3001\u4e00\u90e8\u306e\u6a5f\u80fd\u304c\u5229\u7528\u3067\u304d\u306a\u3044\u3001\u307e\u305f\u306f\u6a5f\u80fd\u3057\u306a\u3044\u304b\u3082\u3057\u308c\u306a\u3044\u3067\u3059\u3002
TimeLineController.rebuildReasons.incompleteOldSchema=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A4\u30D9\u30F3\u30C8\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u4E0D\u5B8C\u5168\u306A\u60C5\u5831\u304C\u4EE5\u524D\u5165\u529B\u3055\u308C\u3066\u3044\u307E\u3057\u305F\uFF1A\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u66F4\u65B0\u3057\u306A\u3044\u3068\u3001\u4E00\u90E8\u306E\u6A5F\u80FD\u304C\u5229\u7528\u3067\u304D\u306A\u3044\u3001\u307E\u305F\u306F\u6A5F\u80FD\u3057\u306A\u3044\u304B\u3082\u3057\u308C\u306A\u3044\u3067\u3059\u3002 TimeLineController.rebuildReasons.ingestWasRunning=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b9f\u884c\u4e2d\u306b\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30a4\u30d9\u30f3\u30c8\u306e\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306b\u60c5\u5831\u304c\u5165\u529b\u3055\u308c\u3066\u3044\u307e\u3057\u305f\uff1a\u30a4\u30d9\u30f3\u30c8\u304c\u6b20\u3051\u3066\u3044\u308b\u3001\u4e0d\u5b8c\u5168\u3001\u307e\u305f\u306f\u4e0d\u6b63\u78ba\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
TimeLineController.rebuildReasons.ingestWasRunning=\u30A4\u30F3\u30B8\u30A7\u30B9\u30C8\u304C\u5B9F\u884C\u4E2D\u306B\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30A4\u30D9\u30F3\u30C8\u306E\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u306B\u60C5\u5831\u304C\u5165\u529B\u3055\u308C\u3066\u3044\u307E\u3057\u305F\uFF1A\u30A4\u30D9\u30F3\u30C8\u304C\u6B20\u3051\u3066\u3044\u308B\u3001\u4E0D\u5B8C\u5168\u3001\u307E\u305F\u306F\u4E0D\u6B63\u78BA\u304B\u3082\u3057\u308C\u307E\u305B\u3093\u3002 TimeLineController.rebuildReasons.outOfDate=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u304c\u6700\u65b0\u3067\u306f\u3042\u308a\u307e\u305b\u3093\uff1a\u898b\u308c\u306a\u3044\u30a4\u30d9\u30f3\u30c8\u304c\u3042\u308a\u307e\u3059\u3002
TimeLineController.rebuildReasons.outOfDate=\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u304C\u6700\u65B0\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF1A\u898B\u308C\u306A\u3044\u30A4\u30D9\u30F3\u30C8\u304C\u3042\u308A\u307E\u3059\u3002 TimeLineController.rebuildReasons.outOfDateError=\u30bf\u30a4\u30e0\u30e9\u30a4\u30f3\u30c7\u30fc\u30bf\u304c\u6700\u65b0\u304b\u78ba\u8a8d\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002
TimeLineController.rebuildReasons.outOfDateError=\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3\u30C7\u30FC\u30BF\u304C\u6700\u65B0\u304B\u78BA\u8A8D\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002 TimeLinecontroller.updateNowQuestion=\u30a4\u30d9\u30f3\u30c8\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u3092\u4eca\u66f4\u65b0\u3057\u307e\u3059\u304b\uff1f
TimeLinecontroller.updateNowQuestion=\u30A4\u30D9\u30F3\u30C8\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u3092\u4ECA\u66F4\u65B0\u3057\u307E\u3059\u304B\uFF1F
TimelinePanel.jButton13.text=\u5168\u3066 TimelinePanel.jButton13.text=\u5168\u3066
Timeline.yearBarChart.x.years=\u5E74 Timeline.yearBarChart.x.years=\u5e74
TimelinePanel.jButton1.text=6\u30F6\u6708 TimelinePanel.jButton1.text=6\u30f6\u6708
TimelinePanel.jButton10.text=1\u6642\u9593 TimelinePanel.jButton10.text=1\u6642\u9593
TimelinePanel.jButton9.text=12\u6642\u9593 TimelinePanel.jButton9.text=12\u6642\u9593
TimelinePanel.jButton11.text=5\u5E74 TimelinePanel.jButton11.text=5\u5e74
TimelinePanel.jButton12.text=10\u5E74 TimelinePanel.jButton12.text=10\u5e74
TimelinePanel.jButton6.text=1\u9031\u9593 TimelinePanel.jButton6.text=1\u9031\u9593
TimelinePanel.jButton5.text=1\u5E74 TimelinePanel.jButton5.text=1\u5e74
TimelinePanel.jButton8.text=1\u65E5 TimelinePanel.jButton8.text=1\u65e5
TimelinePanel.jButton7.text=3\u65E5 TimelinePanel.jButton7.text=3\u65e5
TimelinePanel.jButton2.text=1\u30F6\u6708 TimelinePanel.jButton2.text=1\u30f6\u6708
TimelinePanel.jButton3.text=3\u30F6\u6708 TimelinePanel.jButton3.text=3\u30f6\u6708
TimelinePanel.jButton4.text=2\u9031\u9593 TimelinePanel.jButton4.text=2\u9031\u9593
TimeLineResultView.startDateToEndDate.text={0}\u304b\u3089{1}

View File

@ -18,8 +18,13 @@
*/ */
package org.sleuthkit.autopsy.timeline; package org.sleuthkit.autopsy.timeline;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import org.openide.awt.ActionID; import org.openide.awt.ActionID;
import org.openide.awt.ActionReference; import org.openide.awt.ActionReference;
import org.openide.awt.ActionReferences; import org.openide.awt.ActionReferences;
@ -27,6 +32,7 @@ import org.openide.awt.ActionRegistration;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.openide.util.actions.Presenter;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.core.Installer; import org.sleuthkit.autopsy.core.Installer;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -36,8 +42,9 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined;
@ActionID(category = "Tools", id = "org.sleuthkit.autopsy.timeline.Timeline") @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.timeline.Timeline")
@ActionRegistration(displayName = "#CTL_MakeTimeline", lazy = false) @ActionRegistration(displayName = "#CTL_MakeTimeline", lazy = false)
@ActionReferences(value = { @ActionReferences(value = {
@ActionReference(path = "Menu/Tools", position = 100)}) @ActionReference(path = "Menu/Tools", position = 100),
public class OpenTimelineAction extends CallableSystemAction { @ActionReference(path = "Toolbars/Case", position = 102)})
public class OpenTimelineAction extends CallableSystemAction implements Presenter.Toolbar {
private static final Logger LOGGER = Logger.getLogger(OpenTimelineAction.class.getName()); private static final Logger LOGGER = Logger.getLogger(OpenTimelineAction.class.getName());
@ -45,10 +52,22 @@ public class OpenTimelineAction extends CallableSystemAction {
private static TimeLineController timeLineController = null; private static TimeLineController timeLineController = null;
private JButton toolbarButton = new JButton();
synchronized static void invalidateController() { synchronized static void invalidateController() {
timeLineController = null; timeLineController = null;
} }
public OpenTimelineAction() {
toolbarButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
performAction();
}
});
this.setEnabled(false);
}
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
/** /**
@ -102,4 +121,29 @@ public class OpenTimelineAction extends CallableSystemAction {
public boolean asynchronous() { public boolean asynchronous() {
return false; // run on edt return false; // run on edt
} }
/**
* Set this action to be enabled/disabled
*
* @param value whether to enable this action or not
*/
@Override
public void setEnabled(boolean value) {
super.setEnabled(value);
toolbarButton.setEnabled(value);
}
/**
* Returns the toolbar component of this action
*
* @return component the toolbar button
*/
@Override
public Component getToolbarPresenter() {
ImageIcon icon = new ImageIcon("Core/src/org/sleuthkit/autopsy/timeline/images/btn_icon_timeline_colorized_26.png"); //NON-NLS
toolbarButton.setIcon(icon);
toolbarButton.setText(this.getName());
return toolbarButton;
}
} }

View File

@ -24,6 +24,7 @@ import java.io.IOException;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.TimeZone; import java.util.TimeZone;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@ -188,7 +189,7 @@ public class TimeLineController {
} }
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
private TimeLineTopComponent mainFrame; private TimeLineTopComponent topComponent;
//are the listeners currently attached //are the listeners currently attached
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
@ -199,11 +200,7 @@ public class TimeLineController {
private final PropertyChangeListener ingestModuleListener = new AutopsyIngestModuleListener(); private final PropertyChangeListener ingestModuleListener = new AutopsyIngestModuleListener();
@GuardedBy("this") @GuardedBy("this")
private final ReadOnlyObjectWrapper<VisualizationMode> visualizationMode = new ReadOnlyObjectWrapper<>(VisualizationMode.COUNTS); private final ReadOnlyObjectWrapper<ViewMode> viewMode = new ReadOnlyObjectWrapper<>(ViewMode.COUNTS);
synchronized public ReadOnlyObjectProperty<VisualizationMode> visualizationModeProperty() {
return visualizationMode.getReadOnlyProperty();
}
@GuardedBy("filteredEvents") @GuardedBy("filteredEvents")
private final FilteredEventsModel filteredEvents; private final FilteredEventsModel filteredEvents;
@ -223,21 +220,38 @@ public class TimeLineController {
@GuardedBy("this") @GuardedBy("this")
private final ObservableList<Long> selectedEventIDs = FXCollections.<Long>synchronizedObservableList(FXCollections.<Long>observableArrayList()); private final ObservableList<Long> selectedEventIDs = FXCollections.<Long>synchronizedObservableList(FXCollections.<Long>observableArrayList());
@GuardedBy("this")
private final ReadOnlyObjectWrapper<Interval> selectedTimeRange = new ReadOnlyObjectWrapper<>();
private final ReadOnlyBooleanWrapper eventsDBStale = new ReadOnlyBooleanWrapper(true);
private final PromptDialogManager promptDialogManager = new PromptDialogManager(this);
/** /**
* @return A list of the selected event ids * Get an ObservableList of selected event IDs
*
* @return A list of the selected event IDs
*/ */
synchronized public ObservableList<Long> getSelectedEventIDs() { synchronized public ObservableList<Long> getSelectedEventIDs() {
return selectedEventIDs; return selectedEventIDs;
} }
@GuardedBy("this") /**
private final ReadOnlyObjectWrapper<Interval> selectedTimeRange = new ReadOnlyObjectWrapper<>(); * Get a read only observable view of the selected time range.
*
* @return A read only view of the selected time range.
*/
synchronized public ReadOnlyObjectProperty<Interval> selectedTimeRangeProperty() {
return selectedTimeRange.getReadOnlyProperty();
}
/** /**
* @return a read only view of the selected interval. * Get the selected time range.
*
* @return The selected time range.
*/ */
synchronized public ReadOnlyObjectProperty<Interval> getSelectedTimeRange() { synchronized public Interval getSelectedTimeRange() {
return selectedTimeRange.getReadOnlyProperty(); return selectedTimeRange.get();
} }
public ReadOnlyBooleanProperty eventsDBStaleProperty() { public ReadOnlyBooleanProperty eventsDBStaleProperty() {
@ -282,9 +296,30 @@ public class TimeLineController {
synchronized public ReadOnlyBooleanProperty canRetreatProperty() { synchronized public ReadOnlyBooleanProperty canRetreatProperty() {
return historyManager.getCanRetreat(); return historyManager.getCanRetreat();
} }
private final ReadOnlyBooleanWrapper eventsDBStale = new ReadOnlyBooleanWrapper(true);
private final PromptDialogManager promptDialogManager = new PromptDialogManager(this); synchronized public ReadOnlyObjectProperty<ViewMode> viewModeProperty() {
return viewMode.getReadOnlyProperty();
}
/**
* Set a new ViewMode as the active one.
*
* @param viewMode The new ViewMode to set.
*/
synchronized public void setViewMode(ViewMode viewMode) {
if (this.viewMode.get() != viewMode) {
this.viewMode.set(viewMode);
}
}
/**
* Get the currently active ViewMode.
*
* @return The currently active ViewMode.
*/
synchronized public ViewMode getViewMode() {
return viewMode.get();
}
public TimeLineController(Case autoCase) throws IOException { public TimeLineController(Case autoCase) throws IOException {
this.autoCase = autoCase; this.autoCase = autoCase;
@ -310,6 +345,9 @@ public class TimeLineController {
filteredEvents.filterProperty().get(), filteredEvents.filterProperty().get(),
DescriptionLoD.SHORT); DescriptionLoD.SHORT);
historyManager.advance(InitialZoomState); historyManager.advance(InitialZoomState);
//clear the selected events when the view mode changes
viewMode.addListener(observable -> selectEventIDs(Collections.emptySet()));
} }
/** /**
@ -449,9 +487,9 @@ public class TimeLineController {
IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener); IngestManager.getInstance().removeIngestModuleEventListener(ingestModuleListener);
IngestManager.getInstance().removeIngestJobEventListener(ingestJobListener); IngestManager.getInstance().removeIngestJobEventListener(ingestJobListener);
Case.removePropertyChangeListener(caseListener); Case.removePropertyChangeListener(caseListener);
if (mainFrame != null) { if (topComponent != null) {
mainFrame.close(); topComponent.close();
mainFrame = null; topComponent = null;
} }
OpenTimelineAction.invalidateController(); OpenTimelineAction.invalidateController();
} }
@ -582,17 +620,6 @@ public class TimeLineController {
pushTimeRange(new Interval(start, end)); pushTimeRange(new Interval(start, end));
} }
/**
* Set a new Visualization mode as the active one.
*
* @param visualizationMode The new VisaualizationMode to set.
*/
synchronized public void setVisualizationMode(VisualizationMode visualizationMode) {
if (this.visualizationMode.get() != visualizationMode) {
this.visualizationMode.set(visualizationMode);
}
}
public void selectEventIDs(Collection<Long> events) { public void selectEventIDs(Collection<Long> events) {
final LoggedTask<Interval> selectEventIDsTask = new LoggedTask<Interval>("Select Event IDs", true) { //NON-NLS final LoggedTask<Interval> selectEventIDsTask = new LoggedTask<Interval>("Select Event IDs", true) { //NON-NLS
@Override @Override
@ -624,16 +651,16 @@ public class TimeLineController {
*/ */
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
synchronized private void showWindow() { synchronized private void showWindow() {
if (mainFrame == null) { if (topComponent == null) {
mainFrame = new TimeLineTopComponent(this); topComponent = new TimeLineTopComponent(this);
} }
mainFrame.open(); topComponent.open();
mainFrame.toFront(); topComponent.toFront();
/* /*
* Make this top component active so its ExplorerManager's lookup gets * Make this top component active so its ExplorerManager's lookup gets
* proxied in Utilities.actionsGlobalContext() * proxied in Utilities.actionsGlobalContext()
*/ */
mainFrame.requestActive(); topComponent.requestActive();
} }
synchronized public void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel) { synchronized public void pushEventTypeZoom(EventTypeZoomLevel typeZoomeLevel) {

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