Merge remote-tracking branch 'upstream/develop' into 2210-cleanup

# Conflicts:
#	Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java
This commit is contained in:
millmanorama 2017-05-12 10:47:38 +02:00
commit 6f3f993073
310 changed files with 7948 additions and 2543 deletions

View File

@ -15,7 +15,7 @@
<dependency conf="core->default" org="com.drewnoakes" name="metadata-extractor" rev="2.8.1"/> <dependency conf="core->default" org="com.drewnoakes" name="metadata-extractor" rev="2.8.1"/>
<dependency conf="core->default" org="org.apache.tika" name="tika-core" rev="1.5"/> <dependency conf="core->default" org="org.apache.tika" name="tika-core" rev="1.14"/>
<dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/> <dependency conf="core->default" org="com.adobe.xmp" name="xmpcore" rev="5.1.2"/>
<dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/> <dependency conf="core->default" org="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>

View File

@ -12,7 +12,7 @@ file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbi
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar
file.reference.StixLib.jar=release/modules/ext/StixLib.jar file.reference.StixLib.jar=release/modules/ext/StixLib.jar
file.reference.tika-core-1.5.jar=release/modules/ext/tika-core-1.5.jar file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
file.reference.Tsk_DataModel_PostgreSQL.jar=release/modules/ext/Tsk_DataModel_PostgreSQL.jar file.reference.Tsk_DataModel_PostgreSQL.jar=release/modules/ext/Tsk_DataModel_PostgreSQL.jar
file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar
file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar

View File

@ -243,6 +243,7 @@
<package>net.sf.sevenzipjbinding.simple</package> <package>net.sf.sevenzipjbinding.simple</package>
<package>net.sf.sevenzipjbinding.simple.impl</package> <package>net.sf.sevenzipjbinding.simple.impl</package>
<package>org.sleuthkit.autopsy.actions</package> <package>org.sleuthkit.autopsy.actions</package>
<package>org.sleuthkit.autopsy.appservices</package>
<package>org.sleuthkit.autopsy.casemodule</package> <package>org.sleuthkit.autopsy.casemodule</package>
<package>org.sleuthkit.autopsy.casemodule.events</package> <package>org.sleuthkit.autopsy.casemodule.events</package>
<package>org.sleuthkit.autopsy.casemodule.services</package> <package>org.sleuthkit.autopsy.casemodule.services</package>
@ -254,17 +255,18 @@
<package>org.sleuthkit.autopsy.corecomponents</package> <package>org.sleuthkit.autopsy.corecomponents</package>
<package>org.sleuthkit.autopsy.coreutils</package> <package>org.sleuthkit.autopsy.coreutils</package>
<package>org.sleuthkit.autopsy.datamodel</package> <package>org.sleuthkit.autopsy.datamodel</package>
<package>org.sleuthkit.autopsy.datasourceprocessors</package>
<package>org.sleuthkit.autopsy.directorytree</package> <package>org.sleuthkit.autopsy.directorytree</package>
<package>org.sleuthkit.autopsy.events</package> <package>org.sleuthkit.autopsy.events</package>
<package>org.sleuthkit.autopsy.externalresults</package> <package>org.sleuthkit.autopsy.externalresults</package>
<package>org.sleuthkit.autopsy.filesearch</package> <package>org.sleuthkit.autopsy.filesearch</package>
<package>org.sleuthkit.autopsy.framework</package>
<package>org.sleuthkit.autopsy.ingest</package> <package>org.sleuthkit.autopsy.ingest</package>
<package>org.sleuthkit.autopsy.keywordsearchservice</package> <package>org.sleuthkit.autopsy.keywordsearchservice</package>
<package>org.sleuthkit.autopsy.menuactions</package> <package>org.sleuthkit.autopsy.menuactions</package>
<package>org.sleuthkit.autopsy.modules.filetypeid</package> <package>org.sleuthkit.autopsy.modules.filetypeid</package>
<package>org.sleuthkit.autopsy.modules.hashdatabase</package> <package>org.sleuthkit.autopsy.modules.hashdatabase</package>
<package>org.sleuthkit.autopsy.modules.vmextractor</package> <package>org.sleuthkit.autopsy.modules.vmextractor</package>
<package>org.sleuthkit.autopsy.progress</package>
<package>org.sleuthkit.autopsy.report</package> <package>org.sleuthkit.autopsy.report</package>
<package>org.sleuthkit.datamodel</package> <package>org.sleuthkit.datamodel</package>
</public-packages> </public-packages>
@ -325,8 +327,8 @@
<binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin> <binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/tika-core-1.5.jar</runtime-relative-path> <runtime-relative-path>ext/tika-core-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-core-1.5.jar</binary-origin> <binary-origin>release/modules/ext/tika-core-1.14.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/metadata-extractor-2.8.1.jar</runtime-relative-path> <runtime-relative-path>ext/metadata-extractor-2.8.1.jar</runtime-relative-path>

View File

@ -174,10 +174,6 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
for(BlackboardArtifactTag artifactTag : existingTagsList) { for(BlackboardArtifactTag artifactTag : existingTagsList) {
if(tagDisplayName.equals(artifactTag.getName().getDisplayName())) { if(tagDisplayName.equals(artifactTag.getName().getDisplayName())) {
JMenuItem tagNameItem = new JMenuItem(tagDisplayName); JMenuItem tagNameItem = new JMenuItem(tagDisplayName);
// for the bookmark tag name only, added shortcut label
if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) {
tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT);
}
tagNameItem.addActionListener((ActionEvent e) -> { tagNameItem.addActionListener((ActionEvent e) -> {
deleteTag(tagName, artifactTag, artifact.getArtifactID()); deleteTag(tagName, artifactTag, artifact.getArtifactID());
}); });

View File

@ -159,8 +159,6 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
// a tag with the associated tag name. // a tag with the associated tag name.
if (null != tagNamesMap && !tagNamesMap.isEmpty()) { if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
try { try {
/*List<BlackboardArtifactTag> existingTagsList =
Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact);*/
List<ContentTag> existingTagsList = List<ContentTag> existingTagsList =
Case.getCurrentCase().getServices().getTagsManager() Case.getCurrentCase().getServices().getTagsManager()
.getContentTagsByContent(file); .getContentTagsByContent(file);
@ -172,10 +170,6 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
for(ContentTag contentTag : existingTagsList) { for(ContentTag contentTag : existingTagsList) {
if(tagDisplayName.equals(contentTag.getName().getDisplayName())) { if(tagDisplayName.equals(contentTag.getName().getDisplayName())) {
JMenuItem tagNameItem = new JMenuItem(tagDisplayName); JMenuItem tagNameItem = new JMenuItem(tagDisplayName);
// for the bookmark tag name only, added shortcut label
if (tagDisplayName.equals(NbBundle.getMessage(AddTagAction.class, "AddBookmarkTagAction.bookmark.text"))) {
tagNameItem.setAccelerator(AddBookmarkTagAction.BOOKMARK_SHORTCUT);
}
tagNameItem.addActionListener((ActionEvent e) -> { tagNameItem.addActionListener((ActionEvent e) -> {
deleteTag(tagName, contentTag, file.getId()); deleteTag(tagName, contentTag, file.getId());
}); });

View File

@ -16,9 +16,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.appservices;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.progress.ProgressIndicator;
/** /**
* An interface for services that report status and may manage case and * An interface for services that report status and may manage case and

View File

@ -96,10 +96,10 @@ Case.databaseConnectionInfo.error.msg=Error accessing database server connection
Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0} Case.open.msgDlg.updated.msg=Updated case database schema.\nA backup copy of the database with the following path has been made\:\n {0}
Case.open.msgDlg.updated.title=Case Database Schema Update Case.open.msgDlg.updated.title=Case Database Schema Update
Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user. Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user.
Case.checkImgExist.confDlg.doesntExist.msg={0} has detected that one of the images associated with \n\ Case.checkImgExist.confDlg.doesntExist.msg=One of the images associated with \n\
this case are missing. Would you like to search for them now?\n\ this case are missing. Would you like to search for them now?\n\
Previously, the image was located at\:\n\ Previously, the image was located at\:\n\
{1}\n\ {0}\n\
Please note that you will still be able to browse directories and generate reports\n\ Please note that you will still be able to browse directories and generate reports\n\
if you choose No, but you will not be able to view file content or run the ingest process. if you choose No, but you will not be able to view file content or run the ingest process.
Case.checkImgExist.confDlg.doesntExist.title=Missing Image Case.checkImgExist.confDlg.doesntExist.title=Missing Image
@ -136,12 +136,6 @@ IntervalErrorReport.NewIssues=new issue(s)
IntervalErrorReport.TotalIssues=total issue(s) IntervalErrorReport.TotalIssues=total issue(s)
IntervalErrorReport.ErrorText=Database Connection Error IntervalErrorReport.ErrorText=Database Connection Error
CasePropertiesAction.window.title=Case Properties CasePropertiesAction.window.title=Case Properties
CasePropertiesForm.updateCaseName.msgDlg.empty.msg=The caseName cannot be empty.
CasePropertiesForm.updateCaseName.msgDlg.empty.title=Error
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg=The Case Name cannot contain any of this following symbol\: \\ / \: * ? " < > |
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title=Error
CasePropertiesForm.updateCaseName.confMsg.msg=Are you sure you want to update the case name from "{0}" to "{1}"?
CasePropertiesForm.updateCaseName.confMsg.title=Change Case Name
CueBannerPanel.title.text=Open Recent Case CueBannerPanel.title.text=Open Recent Case
GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin) GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)
GeneralFilter.encaseImageDesc.text=Encase Images (*.e01) GeneralFilter.encaseImageDesc.text=Encase Images (*.e01)

View File

@ -73,10 +73,6 @@ Case.getCurCase.exception.noneOpen=\u4f5c\u696d\u4e2d\u306e\u30b1\u30fc\u30b9\u3
Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\ Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002\n\u6b21\u306e\u30d1\u30b9\u3092\u6301\u3064\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30d0\u30c3\u30af\u30a2\u30c3\u30d7\u30b3\u30d4\u30fc\u304c\u4f5c\u6210\u3055\u308c\u307e\u3057\u305f\uff1a\n\
{0} {0}
Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0 Case.open.msgDlg.updated.title=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u306e\u30b9\u30ad\u30fc\u30de\u3092\u66f4\u65b0
Case.checkImgExist.confDlg.doesntExist.msg={0} \u304c\u3053\u306e\u30b1\u30fc\u30b9\u306b\u95a2\u9023\u3059\u308b\u30a4\u30e1\u30fc\u30b8\u306e\u3046\u3061\uff11\u3064\u304c\u6b20\u843d\u3057\u3066\u3044\u308b\u306e\u3092\u691c\u51fa\u3057\u307e\u3057\u305f\u3002\u305d\u308c\u3092\u4eca\u304b\u3089\u691c\u7d22\u3057\u307e\u3059\u304b\uff1f\n\n\
\u4ee5\u524d\u3001\u30a4\u30e1\u30fc\u30b8\u306f\u6b21\u306b\u3042\u308a\u307e\u3057\u305f\uff1a\n\
{1}\n\
\u3044\u3044\u3048\u3092\u9078\u629e\u3057\u3066\u3082\u3001\u4eca\u5f8c\u3082\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u95b2\u89a7\u3057\u3001\u30ec\u30dd\u30fc\u30c8\u751f\u6210\u304c\u3067\u304d\u307e\u3059\u304c\u3001\n\u30d5\u30a1\u30a4\u30eb\u30b3\u30f3\u30c6\u30f3\u30c4\u306e\u8868\u793a\u307e\u305f\u306f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u30d7\u30ed\u30bb\u30b9\u306e\u5b9f\u884c\u304c\u3067\u304d\u306a\u304f\u306a\u308a\u307e\u3059\u3002
Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8 Case.checkImgExist.confDlg.doesntExist.title=\u6b20\u843d\u3057\u3066\u3044\u308b\u30a4\u30e1\u30fc\u30b8
Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f Case.addImg.exception.msg=\u30b1\u30fc\u30b9\u306b\u30a4\u30e1\u30fc\u30b8\u3092\u8ffd\u52a0\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002 Case.updateCaseName.exception.msg=\u30b1\u30fc\u30b9\u540d\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\u3002
@ -99,10 +95,6 @@ CaseDeleteAction.msgDlg.caseDelete.msg=\u30b1\u30fc\u30b9\u304c\u524a\u9664\u305
CaseOpenAction.autFilter.title={0} \u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb ( {1}) CaseOpenAction.autFilter.title={0} \u30b1\u30fc\u30b9\u30d5\u30a1\u30a4\u30eb ( {1})
CaseOpenAction.msgDlg.cantOpenCase.title=\u30b1\u30fc\u30b9\u3092\u958b\u304f\u969b\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f CaseOpenAction.msgDlg.cantOpenCase.title=\u30b1\u30fc\u30b9\u3092\u958b\u304f\u969b\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
CasePropertiesAction.window.title=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3 CasePropertiesAction.window.title=\u30b1\u30fc\u30b9\u30d7\u30ed\u30d1\u30c6\u30a3
CasePropertiesForm.updateCaseName.msgDlg.empty.msg=\u30b1\u30fc\u30b9\u540d\u306f\u7a7a\u767d\u3067\u306f\u3044\u3051\u307e\u305b\u3093\u3002
CasePropertiesForm.updateCaseName.msgDlg.empty.title=\u30a8\u30e9\u30fc
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.msg=\u30b1\u30fc\u30b9\u540d\u306b\u306f\u6b21\u306e\u8a18\u53f7\u3092\u542b\u3081\u307e\u305b\u3093\uff1a\\ / \: * ? " < > |
CasePropertiesForm.updateCaseName.msgDlg.invalidSymbols.title=\u30a8\u30e9\u30fc
CueBannerPanel.title.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f CueBannerPanel.title.text=\u6700\u8fd1\u958b\u3044\u305f\u30b1\u30fc\u30b9\u3092\u958b\u304f
GeneralFilter.rawImageDesc.text=\u30ed\u30fc\u30a4\u30e1\u30fc\u30b8(*.img, *.dd, *.001, *.aa, *.raw, *.bin) GeneralFilter.rawImageDesc.text=\u30ed\u30fc\u30a4\u30e1\u30fc\u30b8(*.img, *.dd, *.001, *.aa, *.raw, *.bin)
GeneralFilter.encaseImageDesc.text=\u30a8\u30f3\u30b1\u30fc\u30b9\u30a4\u30e1\u30fc\u30b8(*.e01) GeneralFilter.encaseImageDesc.text=\u30a8\u30f3\u30b1\u30fc\u30b9\u30a4\u30e1\u30fc\u30b8(*.e01)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,49 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.casemodule;
/**
* Exception thrown when a case action (e.g., create, open, close, delete) is
* cancelled before it is completed.
*/
public final class CaseActionCancelledException extends CaseActionException {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) is cancelled before it is completed.
*
* @param message An error message.
*/
CaseActionCancelledException(String message) {
super(message);
}
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) is cancelled before it is completed.
*
* @param message An error message.
* @param cause An excception that caused this exception to be thrown.
*/
CaseActionCancelledException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2012 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,15 +19,30 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
/** /**
* Exception thrown when case action (such as open, close, create) resulted in * Exception thrown when a case action (e.g., create, open, close, delete)
* an error * experiences an error condition.
*/ */
public class CaseActionException extends Exception { public class CaseActionException extends Exception {
private static final long serialVersionUID = 1L;
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) experiences an error condition.
*
* @param message An error message.
*/
public CaseActionException(String message) { public CaseActionException(String message) {
super(message); super(message);
} }
/**
* Constructs an exception thrown when a case action (e.g., create, open,
* close, delete) experiences an error condition.
*
* @param message An error message.
* @param cause An excception that caused this exception to be thrown.
*/
public CaseActionException(String message, Throwable cause) { public CaseActionException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }

View File

@ -90,7 +90,7 @@ final class CaseDeleteAction extends CallableSystemAction {
logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex); logger.log(Level.SEVERE, String.format("Failed to delete case %s at %s", caseName, caseDirectory), ex);
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
null, null,
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getMessage()), Bundle.Case_deleteCaseFailureMessageBox_message(ex.getLocalizedMessage()),
Bundle.Case_deleteCaseFailureMessageBox_title(), Bundle.Case_deleteCaseFailureMessageBox_title(),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
} }
@ -99,6 +99,7 @@ final class CaseDeleteAction extends CallableSystemAction {
* of the Delete button that invokes this action. * of the Delete button that invokes this action.
*/ */
CasePropertiesAction.closeCasePropertiesWindow(); CasePropertiesAction.closeCasePropertiesWindow();
StartupWindowProvider.getInstance().open();
} }
}.execute(); }.execute();
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org * Contact: carrier <at> sleuthkit <dot> org
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
@ -19,10 +19,6 @@
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeEvent;
import org.openide.util.NbBundle.Messages; import org.openide.util.NbBundle.Messages;
@ -32,44 +28,40 @@ import org.openide.util.NbBundle.Messages;
*/ */
class CaseInformationPanel extends javax.swing.JPanel { class CaseInformationPanel extends javax.swing.JPanel {
private static final Logger logger = Logger.getLogger(CaseInformationPanel.class.getName()); private static final long serialVersionUID = 1L;
/** /**
* Creates new form CaseInformationPanel * Constructs a panel for displaying the case information, including both
* case details and ingest job history.
*/ */
CaseInformationPanel() { CaseInformationPanel() {
initComponents(); initComponents();
customizeComponents(); customizeComponents();
} }
@Messages({"CaseInformationPanel.caseDetails.header=Case Details", @Messages({
"CaseInformationPanel.ingestJobInfo.header=Ingest History", "CaseInformationPanel.caseDetails.header=Case Details",
"CaseInformationPanel.loadMetadataFail.message=Failed to load case metadata.", "CaseInformationPanel.ingestJobInfo.header=Ingest History"
"CaseInformationPanel.loadMetadataFail.title=Metadata load failure",}) })
private void customizeComponents() { private void customizeComponents() {
try { CasePropertiesPanel propertiesPanel = new CasePropertiesPanel(Case.getCurrentCase());
Case currentCase = Case.getCurrentCase(); propertiesPanel.setSize(propertiesPanel.getPreferredSize());
String crDate = currentCase.getCreatedDate(); this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), propertiesPanel);
String caseDir = currentCase.getCaseDirectory(); this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel());
this.tabbedPane.addChangeListener((ChangeEvent e) -> {
// put the image paths information into hashmap tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize());
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase()); });
CasePropertiesPanel cpf = new CasePropertiesPanel(currentCase, crDate, caseDir, imgPaths);
cpf.setSize(cpf.getPreferredSize());
this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), cpf);
this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel());
this.tabbedPane.addChangeListener((ChangeEvent e) -> {
tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize());
});
} catch (CaseMetadata.CaseMetadataException ex) {
logger.log(Level.SEVERE, "Failed to load case metadata.", ex);
JOptionPane.showMessageDialog(null, Bundle.IngestJobInfoPanel_loadIngestJob_error_text(), Bundle.IngestJobInfoPanel_loadIngestJob_error_title(), JOptionPane.ERROR_MESSAGE);
}
} }
/**
* Adds an action listener to the Close button of the panel.
*
* @param action
*/
void addCloseButtonAction(ActionListener action) { void addCloseButtonAction(ActionListener action) {
this.closeButton.addActionListener(action); this.closeButton.addActionListener(action);
} }
/** /**
* 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
@ -127,7 +119,7 @@ class CaseInformationPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
// TODO add your handling code here: // Used by CasePropertiesAction
}//GEN-LAST:event_closeButtonActionPerformed }//GEN-LAST:event_closeButtonActionPerformed

View File

@ -54,7 +54,9 @@ public final class CaseMetadata {
private static final String FILE_EXTENSION = ".aut"; private static final String FILE_EXTENSION = ".aut";
private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)"); private static final DateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
//fields from schema version 1 /*
* Fields from schema version 1
*/
private static final String SCHEMA_VERSION_ONE = "1.0"; private static final String SCHEMA_VERSION_ONE = "1.0";
private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS private final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //NON-NLS
private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS private final static String SCHEMA_VERSION_ELEMENT_NAME = "SchemaVersion"; //NON-NLS
@ -68,22 +70,28 @@ public final class CaseMetadata {
private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS private final static String CASE_DATABASE_NAME_ELEMENT_NAME = "DatabaseName"; //NON-NLS
private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS private final static String TEXT_INDEX_NAME_ELEMENT = "TextIndexName"; //NON-NLS
//fields from schema version 2 /*
* Fields from schema version 2
*/
private static final String SCHEMA_VERSION_TWO = "2.0"; private static final String SCHEMA_VERSION_TWO = "2.0";
private final static String AUTOPSY_CREATED_BY_ELEMENT_NAME = "CreatedByAutopsyVersion"; //NON-NLS private final static String AUTOPSY_CREATED_BY_ELEMENT_NAME = "CreatedByAutopsyVersion"; //NON-NLS
private final static String CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME = "Database"; //NON-NLS private final static String CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME = "Database"; //NON-NLS
private final static String TEXT_INDEX_ELEMENT = "TextIndex"; //NON-NLS private final static String TEXT_INDEX_ELEMENT = "TextIndex"; //NON-NLS
//fields from schema version 3 /*
* Fields from schema version 3
*/
private static final String SCHEMA_VERSION_THREE = "3.0"; private static final String SCHEMA_VERSION_THREE = "3.0";
private final static String CASE_DISPLAY_NAME_ELEMENT_NAME = "DisplayName"; //NON-NLS private final static String CASE_DISPLAY_NAME_ELEMENT_NAME = "DisplayName"; //NON-NLS
private final static String CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME = "CaseDatabase"; //NON-NLS private final static String CASE_DB_NAME_RELATIVE_ELEMENT_NAME = "CaseDatabase"; //NON-NLS
//unread fields, these are regenerated on save /*
* Unread fields, regenerated on save.
*/
private final static String MODIFIED_DATE_ELEMENT_NAME = "ModifiedDate"; //NON-NLS private final static String MODIFIED_DATE_ELEMENT_NAME = "ModifiedDate"; //NON-NLS
private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS private final static String AUTOPSY_SAVED_BY_ELEMENT_NAME = "SavedByAutopsyVersion"; //NON-NLS
private static final String CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_THREE; private final static String CURRENT_SCHEMA_VERSION = SCHEMA_VERSION_THREE;
private final Path metadataFilePath; private final Path metadataFilePath;
private Case.CaseType caseType; private Case.CaseType caseType;
@ -92,8 +100,8 @@ public final class CaseMetadata {
private String caseNumber; private String caseNumber;
private String examiner; private String examiner;
private String caseDatabaseName; private String caseDatabaseName;
private String caseDatabasePath; private String caseDatabasePath; // Legacy
private String textIndexName; private String textIndexName; // Legacy
private String createdDate; private String createdDate;
private String createdByVersion; private String createdByVersion;
@ -107,8 +115,9 @@ public final class CaseMetadata {
} }
/** /**
* Constructs an object that provides access to the case metadata stored in * Constructs a CaseMetadata object for a new case. The metadata is not
* a new case metadata file that is created using the supplied metadata. * persisted to the case metadata file until writeFile or a setX method is
* called.
* *
* @param caseDirectory The case directory. * @param caseDirectory The case directory.
* @param caseType The type of case. * @param caseType The type of case.
@ -117,29 +126,24 @@ public final class CaseMetadata {
* user. * user.
* @param caseNumber The case number. * @param caseNumber The case number.
* @param examiner The name of the case examiner. * @param examiner The name of the case examiner.
* @param caseDatabase For a single-user case, the full path to the case
* database file. For a multi-user case, the case
* database name.
*
* @throws CaseMetadataException If the new case metadata file cannot be
* created.
*/ */
CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner, String caseDatabase) throws CaseMetadataException { CaseMetadata(String caseDirectory, Case.CaseType caseType, String caseName, String caseDisplayName, String caseNumber, String examiner) {
metadataFilePath = Paths.get(caseDirectory, caseDisplayName + FILE_EXTENSION); metadataFilePath = Paths.get(caseDirectory, caseDisplayName + FILE_EXTENSION);
this.caseType = caseType; this.caseType = caseType;
this.caseName = caseName; this.caseName = caseName;
this.caseDisplayName = caseDisplayName; this.caseDisplayName = caseDisplayName;
this.caseNumber = caseNumber; this.caseNumber = caseNumber;
this.examiner = examiner; this.examiner = examiner;
this.caseDatabaseName = caseDatabase; caseDatabaseName = "";
caseDatabasePath = "";
textIndexName = "";
createdByVersion = Version.getVersion(); createdByVersion = Version.getVersion();
createdDate = CaseMetadata.DATE_FORMAT.format(new Date()); createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
writeToFile();
} }
/** /**
* Constructs an object that provides access to the case metadata stored in * Constructs a CaseMetadata object for an existing case. The metadata is
* an existing case metadata file. * read from an existing case metadata file.
* *
* @param metadataFilePath The full path to the case metadata file. * @param metadataFilePath The full path to the case metadata file.
* *
@ -179,7 +183,7 @@ public final class CaseMetadata {
} }
/** /**
* Gets the immutable case name, set at case creation. * Gets the unique and immutable case name.
* *
* @return The case display name. * @return The case display name.
*/ */
@ -193,22 +197,23 @@ public final class CaseMetadata {
* @return The case display name. * @return The case display name.
*/ */
public String getCaseDisplayName() { public String getCaseDisplayName() {
return this.caseDisplayName; return caseDisplayName;
} }
/** /**
* Sets the case display name. This does not change the name of the case * Sets the case display name.
* directory, the case database, or the text index name.
* *
* @param caseName A case display name. * @param caseDisplayName A case display name.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setCaseDisplayName(String caseName) throws CaseMetadataException { void setCaseDisplayName(String caseDisplayName) throws CaseMetadataException {
String oldCaseName = caseName; String oldCaseDisplayName = this.caseDisplayName;
this.caseDisplayName = caseName; this.caseDisplayName = caseDisplayName;
try { try {
writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.caseDisplayName = oldCaseName; this.caseDisplayName = oldCaseDisplayName;
throw ex; throw ex;
} }
} }
@ -234,32 +239,35 @@ public final class CaseMetadata {
/** /**
* Gets the name of the case database. * Gets the name of the case database.
* *
* @return The case database name. * @return The case database name, may be empty.
*/ */
public String getCaseDatabaseName() { public String getCaseDatabaseName() {
return caseDatabaseName; return caseDatabaseName;
} }
/** /**
* Sets the text index name. * Sets the name of the case database.
* *
* @param caseTextIndexName The text index name. * @param caseDatabaseName The case database name.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setTextIndexName(String caseTextIndexName) throws CaseMetadataException { void setCaseDatabaseName(String caseDatabaseName) throws CaseMetadataException {
String oldIndexName = caseTextIndexName; String oldCaseDatabaseName = this.caseDatabaseName;
this.textIndexName = caseTextIndexName; this.caseDatabaseName = caseDatabaseName;
try { try {
writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.textIndexName = oldIndexName; this.caseDatabaseName = oldCaseDatabaseName;
throw ex; throw ex;
} }
} }
/** /**
* Gets the text index name. * Gets the text index name. This is a legacy field and will be empty for
* cases created with Autopsy 4.4.0 and above.
* *
* @return The name of the text index for the case. * @return The name of the text index for the case, may be empty.
*/ */
public String getTextIndexName() { public String getTextIndexName() {
return textIndexName; return textIndexName;
@ -268,7 +276,7 @@ public final class CaseMetadata {
/** /**
* Gets the date the case was created. * Gets the date the case was created.
* *
* @return The date this case was created as a string * @return The date this case was created, as a string.
*/ */
String getCreatedDate() { String getCreatedDate() {
return createdDate; return createdDate;
@ -278,7 +286,9 @@ public final class CaseMetadata {
* Sets the date the case was created. Used for preserving the case creation * Sets the date the case was created. Used for preserving the case creation
* date during single-user to multi-user case conversion. * date during single-user to multi-user case conversion.
* *
* @param createdDate The date the case was created as a string. * @param createdDate The date the case was created, as a string.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setCreatedDate(String createdDate) throws CaseMetadataException { void setCreatedDate(String createdDate) throws CaseMetadataException {
String oldCreatedDate = createdDate; String oldCreatedDate = createdDate;
@ -304,13 +314,15 @@ public final class CaseMetadata {
* Sets the Autopsy version that created the case. Used for preserving this * Sets the Autopsy version that created the case. Used for preserving this
* metadata during single-user to multi-user case conversion. * metadata during single-user to multi-user case conversion.
* *
* @param buildVersion An build version identifier. * @param buildVersion A build version identifier.
*
* @throws CaseMetadataException If the operation fails.
*/ */
void setCreatedByVersion(String buildVersion) throws CaseMetadataException { void setCreatedByVersion(String buildVersion) throws CaseMetadataException {
String oldCreatedByVersion = this.createdByVersion; String oldCreatedByVersion = this.createdByVersion;
this.createdByVersion = buildVersion; this.createdByVersion = buildVersion;
try { try {
this.writeToFile(); writeToFile();
} catch (CaseMetadataException ex) { } catch (CaseMetadataException ex) {
this.createdByVersion = oldCreatedByVersion; this.createdByVersion = oldCreatedByVersion;
throw ex; throw ex;
@ -381,8 +393,8 @@ public final class CaseMetadata {
createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber); createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber);
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner); createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString()); createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString());
createChildElement(doc, caseElement, CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME, caseDatabasePath); createChildElement(doc, caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, caseDatabasePath);
createChildElement(doc, caseElement, CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME, caseDatabaseName); createChildElement(doc, caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, caseDatabaseName);
createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName); createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
} }
@ -451,15 +463,19 @@ public final class CaseMetadata {
if (null == this.caseType) { if (null == this.caseType) {
throw new CaseMetadataException("Case metadata file corrupted"); throw new CaseMetadataException("Case metadata file corrupted");
} }
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) { switch (schemaVersion) {
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true); case SCHEMA_VERSION_ONE:
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true); this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
} else if (schemaVersion.equals(SCHEMA_VERSION_TWO)) { this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME, true); break;
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false); case SCHEMA_VERSION_TWO:
} else { this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, true);
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME, true); this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false); break;
default:
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, true);
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
break;
} }
/* /*
@ -489,7 +505,7 @@ public final class CaseMetadata {
* @param elementName The element name. * @param elementName The element name.
* @param contentIsRequired Whether or not the content is required. * @param contentIsRequired Whether or not the content is required.
* *
* @return The text content, may be empty if not required. * @return The text content, may be empty If not required.
* *
* @throws CaseMetadataException If the element is missing or content is * @throws CaseMetadataException If the element is missing or content is
* required and it is empty. * required and it is empty.
@ -530,7 +546,7 @@ public final class CaseMetadata {
* @return The full path to the case database file for a single-user case. * @return The full path to the case database file for a single-user case.
* *
* @throws UnsupportedOperationException If called for a multi-user case. * @throws UnsupportedOperationException If called for a multi-user case.
* @deprecated * @deprecated Do not use.
*/ */
@Deprecated @Deprecated
public String getCaseDatabasePath() throws UnsupportedOperationException { public String getCaseDatabasePath() throws UnsupportedOperationException {

View File

@ -115,26 +115,19 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
protected void done() { protected void done() {
try { try {
get(); get();
} catch (InterruptedException ex) { } catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS if (ex instanceof InterruptedException || (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException))) {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
JOptionPane.showMessageDialog( JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(), WindowManager.getDefault().getMainWindow(),
ex.getMessage(), ex.getCause().getMessage(), //get the message of the wrapped exception
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
}
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
} catch (ExecutionException ex) { } finally {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
JOptionPane.showMessageDialog(
WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(), //get the message of the wrapped exception
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
StartupWindowProvider.getInstance().open();
} }
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }
}.execute(); }.execute();
} }

View File

@ -22,7 +22,6 @@ import java.awt.Dimension;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.Action; import javax.swing.Action;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -43,34 +42,29 @@ final class CasePropertiesAction extends CallableSystemAction {
CasePropertiesAction() { CasePropertiesAction() {
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction")); putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction"));
this.setEnabled(false); this.setEnabled(false);
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() { Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent evt) -> {
@Override setEnabled(null != evt.getNewValue());
public void propertyChange(PropertyChangeEvent evt) {
setEnabled(null != evt.getNewValue());
}
}); });
} }
@Override @Override
public void performAction() { public void performAction() {
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
if (null == casePropertiesDialog) { String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title"); casePropertiesDialog = new JDialog(WindowManager.getDefault().getMainWindow(), title, false);
casePropertiesDialog = new JDialog(WindowManager.getDefault().getMainWindow(), title, false); CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
CaseInformationPanel caseInformationPanel = new CaseInformationPanel(); caseInformationPanel.addCloseButtonAction((ActionEvent e) -> {
caseInformationPanel.addCloseButtonAction((ActionEvent e) -> { casePropertiesDialog.setVisible(false);
casePropertiesDialog.setVisible(false); });
}); casePropertiesDialog.add(caseInformationPanel);
casePropertiesDialog.add(caseInformationPanel); casePropertiesDialog.setResizable(true);
casePropertiesDialog.setResizable(true); casePropertiesDialog.pack();
casePropertiesDialog.pack();
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
double w = casePropertiesDialog.getSize().getWidth(); double w = casePropertiesDialog.getSize().getWidth();
double h = casePropertiesDialog.getSize().getHeight(); double h = casePropertiesDialog.getSize().getHeight();
casePropertiesDialog.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2)); casePropertiesDialog.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
casePropertiesDialog.setVisible(true); casePropertiesDialog.setVisible(true);
}
casePropertiesDialog.setVisible(true); casePropertiesDialog.setVisible(true);
casePropertiesDialog.toFront(); casePropertiesDialog.toFront();
}); });
@ -87,6 +81,9 @@ final class CasePropertiesAction extends CallableSystemAction {
} }
static void closeCasePropertiesWindow() { static void closeCasePropertiesWindow() {
casePropertiesDialog.setVisible(false); if (null != casePropertiesDialog) {
casePropertiesDialog.setVisible(false);
casePropertiesDialog = null;
}
} }
} }

View File

@ -16,63 +16,57 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.casemodule; package org.sleuthkit.autopsy.casemodule;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Map;
import java.util.logging.Level; import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.actions.CallableSystemAction; import org.openide.util.actions.CallableSystemAction;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/** /**
* A panel that allows the user to view various properties of the current case * A panel that allows the user to view various properties of a case and change
* and change the display name of the case. * the display name of the case.
*/ */
class CasePropertiesPanel extends javax.swing.JPanel { class CasePropertiesPanel extends javax.swing.JPanel {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private Case current = null; private static final Logger LOGGER = Logger.getLogger(CasePropertiesPanel.class.getName());
private static JPanel caller; // panel for error private final Case theCase;
CasePropertiesPanel(Case currentCase, String crDate, String caseDir, Map<Long, String> imgPaths) throws CaseMetadata.CaseMetadataException { /**
* Constructs a panel that allows the user to view various properties of the
* current case and change the display name of the case.
*
* @param aCase A case.
*/
CasePropertiesPanel(Case aCase) {
initComponents(); initComponents();
caseNameTextField.setText(currentCase.getDisplayName()); theCase = aCase;
String caseNumber = currentCase.getNumber(); caseNameTextField.setText(theCase.getDisplayName());
String caseNumber = theCase.getNumber();
if (!caseNumber.isEmpty()) { if (!caseNumber.isEmpty()) {
caseNumberField.setText(caseNumber); caseNumberField.setText(caseNumber);
} else { } else {
caseNumberField.setText("N/A"); caseNumberField.setText("N/A");
} }
String examiner = currentCase.getExaminer(); String examiner = theCase.getExaminer();
if (!examiner.isEmpty()) { if (!examiner.isEmpty()) {
examinerField.setText(examiner); examinerField.setText(examiner);
} else { } else {
examinerField.setText("N/A"); examinerField.setText("N/A");
} }
crDateField.setText(crDate); crDateField.setText(theCase.getCreatedDate());
caseDirField.setText(caseDir); caseDirField.setText(theCase.getCaseDirectory());
current = currentCase; if (Case.CaseType.SINGLE_USER_CASE == theCase.getCaseType()) {
dbNameField.setText(Paths.get(theCase.getCaseDirectory(), theCase.getMetadata().getCaseDatabaseName()).toString());
CaseMetadata caseMetadata = currentCase.getCaseMetadata();
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
dbNameField.setText(Paths.get(caseMetadata.getCaseDirectory(), caseMetadata.getCaseDatabaseName()).toString());
} else { } else {
dbNameField.setText(caseMetadata.getCaseDatabaseName()); dbNameField.setText(theCase.getMetadata().getCaseDatabaseName());
} }
Case.CaseType caseType = caseMetadata.getCaseType(); Case.CaseType caseType = theCase.getCaseType();
caseTypeField.setText(caseType.getLocalizedDisplayName()); caseTypeField.setText(caseType.getLocalizedDisplayName());
if (caseType == Case.CaseType.SINGLE_USER_CASE) { deleteCaseButton.setEnabled(Case.CaseType.SINGLE_USER_CASE == caseType);
deleteCaseButton.setEnabled(true);
} else {
deleteCaseButton.setEnabled(false);
}
} }
/** /**
@ -259,59 +253,35 @@ class CasePropertiesPanel extends javax.swing.JPanel {
}// </editor-fold>//GEN-END:initComponents }// </editor-fold>//GEN-END:initComponents
/** /**
* Updates the case name. * Updates the case display name.
* *
* @param evt The action event * @param evt The action event
*/ */
@NbBundle.Messages({
"CasePropertiesPanel.errorDialog.emptyCaseNameMessage=No case name entered.",
"CasePropertiesPanel.errorDialog.invalidCaseNameMessage=Case names cannot include the following symbols: \\, /, :, *, ?, \", <, >, |"
})
private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed private void updateCaseNameButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_updateCaseNameButtonActionPerformed
String oldCaseName = Case.getCurrentCase().getDisplayName(); String newCaseDisplayName = caseNameTextField.getText();
String newCaseName = caseNameTextField.getText(); if (newCaseDisplayName.equals(theCase.getDisplayName())) {
// check if the old and new case name is not equal return;
if (!oldCaseName.equals(newCaseName)) { }
// check if the case name is empty if (newCaseDisplayName.trim().isEmpty()) {
if (newCaseName.trim().isEmpty()) { MessageNotifyUtil.Message.error(Bundle.CasePropertiesPanel_errorDialog_emptyCaseNameMessage());
JOptionPane.showMessageDialog(caller, return;
NbBundle.getMessage(this.getClass(), }
"CasePropertiesForm.updateCaseName.msgDlg.empty.msg"),
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.msgDlg.empty.title"),
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 {
// ask for the confirmation first
String confMsg = NbBundle
.getMessage(this.getClass(), "CasePropertiesForm.updateCaseName.confMsg.msg", oldCaseName,
newCaseName);
NotifyDescriptor d = new NotifyDescriptor.Confirmation(confMsg,
NbBundle.getMessage(this.getClass(),
"CasePropertiesForm.updateCaseName.confMsg.title"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.WARNING_MESSAGE);
d.setValue(NotifyDescriptor.NO_OPTION);
Object res = DialogDisplayer.getDefault().notify(d); if (!Case.isValidName(newCaseDisplayName)) {
if (res != null && res == DialogDescriptor.YES_OPTION) { MessageNotifyUtil.Message.error(Bundle.CasePropertiesPanel_errorDialog_invalidCaseNameMessage());
// if user select "Yes" return;
String oldPath = current.getCaseMetadata().getFilePath().toString(); }
try {
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath); try {
} catch (CaseActionException ex) { theCase.updateDisplayName(newCaseDisplayName);
Logger.getLogger(CasePropertiesPanel.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS } catch (CaseActionException ex) {
} MessageNotifyUtil.Message.error(ex.getLocalizedMessage());
} LOGGER.log(Level.SEVERE, "Failed to update case display name", ex); //NON-NLS
}
}
} }
}//GEN-LAST:event_updateCaseNameButtonActionPerformed }//GEN-LAST:event_updateCaseNameButtonActionPerformed

View File

@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DataSourceUtils; import org.sleuthkit.autopsy.coreutils.DataSourceUtils;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
/** /**
* A image file data source processor that implements the DataSourceProcessor * A image file data source processor that implements the DataSourceProcessor

View File

@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.coreutils.DriveUtils; import org.sleuthkit.autopsy.coreutils.DriveUtils;
import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings; import org.sleuthkit.autopsy.imagewriter.ImageWriterSettings;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
/** /**
* A local drive data source processor that implements the DataSourceProcessor * A local drive data source processor that implements the DataSourceProcessor

View File

@ -29,7 +29,7 @@ import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
/** /**
* A local/logical files and/or directories data source processor that * A local/logical files and/or directories data source processor that

View File

@ -94,15 +94,17 @@ final class NewCaseWizardAction extends CallableSystemAction {
AddImageAction addImageAction = SystemAction.get(AddImageAction.class); AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
addImageAction.actionPerformed(null); addImageAction.actionPerformed(null);
} catch (InterruptedException | ExecutionException ex) { } catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
JOptionPane.showMessageDialog( logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
WindowManager.getDefault().getMainWindow(), JOptionPane.showMessageDialog(
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()), WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS (ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
JOptionPane.ERROR_MESSAGE); NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
}
doFailedCaseCleanup(wizardDescriptor);
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
doFailedCaseCleanup(wizardDescriptor);
} finally { } finally {
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }

View File

@ -38,29 +38,21 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.ModuleSettings;
/** /**
* The "New Case" wizard panel with a component on it. This class represents * The first panel of the New Case wizard.
* data of wizard step. It defers creation and initialization of UI component of
* wizard panel into getComponent() method.
*/ */
class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> { class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private NewCaseVisualPanel1 component;
private Boolean isFinish = false;
private static String createdDirectory;
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
private static final Logger logger = Logger.getLogger(NewCaseWizardPanel1.class.getName()); private static final Logger logger = Logger.getLogger(NewCaseWizardPanel1.class.getName());
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
private static String createdDirectory;
private final Set<ChangeListener> listeners = new HashSet<>(1);
private NewCaseVisualPanel1 component;
private boolean isFinish;
/** /**
* Get the visual component for the panel. In this template, the component * Get the visual component for the panel.
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
* *
* @return component the UI component of this wizard panel * @return The UI component of this wizard panel
*/ */
@Override @Override
public NewCaseVisualPanel1 getComponent() { public NewCaseVisualPanel1 getComponent() {
@ -71,65 +63,57 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
/** /**
* Help for this panel. When the panel is active, this is used as the help * Gets the help object for this panel. When the panel is active, this is
* for the wizard dialog. * used as the help for the wizard dialog.
* *
* @return HelpCtx.DEFAULT_HELP the help for this panel * @return The help for this panel.
*/ */
@Override @Override
public HelpCtx getHelp() { public HelpCtx getHelp() {
// Show no Help button for this panel: /*
* Currently, no help is provided for this panel.
*/
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
} }
/** /**
* Tests whether the panel is finished. If the panel is valid, the "Finish" * Tests whether the panel is finished. If the panel is valid, the "Finish"
* button will be enabled. * button will be enabled.
* *
* @return boolean true if all the fields are correctly filled, false * @return boolean True if all the fields are correctly filled, false
* otherwise * otherwise.
*/ */
@Override @Override
public boolean isValid() { public boolean isValid() {
// If it is always OK to press Next or Finish, then:
return isFinish; return isFinish;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
} }
private final Set<ChangeListener> listeners = new HashSet<>(1); // or can use ChangeSupport in NB 6.0
/** /**
* Adds a listener to changes of the panel's validity. * Adds a change listener to this panel.
* *
* @param l the change listener to add * @param listener The change listener to add.
*/ */
@Override @Override
public final void addChangeListener(ChangeListener l) { public final void addChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.add(l); listeners.add(listener);
} }
} }
/** /**
* Removes a listener to changes of the panel's validity. * Removes a change listener from this panel.
* *
* @param l the change listener to move * @param listener The change listener to remove.
*/ */
@Override @Override
public final void removeChangeListener(ChangeListener l) { public final void removeChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.remove(l); listeners.remove(listener);
} }
} }
/** /**
* This method is auto-generated. It seems that this method is used to * Notifies any registerd change listeners of a change in the panel.
* listen to any change in this wizard panel.
*/ */
protected final void fireChangeEvent() { protected final void fireChangeEvent() {
Iterator<ChangeListener> it; Iterator<ChangeListener> it;
@ -153,12 +137,8 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
fireChangeEvent(); fireChangeEvent();
} }
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/** /**
* Provides the wizard panel with the current data--either the default data * Provides the wizard panel with the current data - either the default data
* or already-modified settings, if the user used the previous and/or next * or already-modified settings, if the user used the previous and/or next
* buttons. This method can be called multiple times on one instance of * buttons. This method can be called multiple times on one instance of
* WizardDescriptor.Panel. * WizardDescriptor.Panel.
@ -322,4 +302,5 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
} }
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 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");
@ -28,35 +28,19 @@ import org.openide.WizardValidationException;
import org.openide.util.HelpCtx; import org.openide.util.HelpCtx;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
import java.awt.Cursor; import java.awt.Cursor;
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
/** /**
* The "New Case" wizard panel with a component on it. This class represents * The second panel of the New Case wizard.
* data of wizard step. It defers creation and initialization of UI component of
* wizard panel into getComponent() method.
*
* @author jantonius
*/ */
class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> { class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDescriptor> {
/**
* The visual component that displays this panel. If you need to access the
* component from this class, just use getComponent().
*/
private NewCaseVisualPanel2 component; private NewCaseVisualPanel2 component;
private Boolean isFinish = true; private final Set<ChangeListener> listeners = new HashSet<>(1);
private String caseName;
private String caseDir;
private String createdDirectory;
private CaseType caseType;
/** /**
* Get the visual component for the panel. In this template, the component * Get the visual component for the panel.
* is kept separate. This can be more efficient: if the wizard is created
* but never displayed, or not all panels are displayed, it is better to
* create only those which really need to be visible.
* *
* @return component the UI component of this wizard panel * @return component The UI component of this wizard panel.
*/ */
@Override @Override
public NewCaseVisualPanel2 getComponent() { public NewCaseVisualPanel2 getComponent() {
@ -67,17 +51,17 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
/** /**
* Help for this panel. When the panel is active, this is used as the help * Gets the help object for this panel. When the panel is active, this is
* for the wizard dialog. * used as the help for the wizard dialog.
* *
* @return HelpCtx.DEFAULT_HELP the help for this panel * @return The help for this panel.
*/ */
@Override @Override
public HelpCtx getHelp() { public HelpCtx getHelp() {
// Show no Help button for this panel: /*
* Currently, no help is provided for this panel.
*/
return HelpCtx.DEFAULT_HELP; return HelpCtx.DEFAULT_HELP;
// If you have context help:
// return new HelpCtx(SampleWizardPanel1.class);
} }
/** /**
@ -89,43 +73,35 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
*/ */
@Override @Override
public boolean isValid() { public boolean isValid() {
// If it is always OK to press Next or Finish, then: return true;
return isFinish;
// If it depends on some condition (form filled out...), then:
// return someCondition();
// and when this condition changes (last form field filled in...) then:
// fireChangeEvent();
// and uncomment the complicated stuff below.
} }
private final Set<ChangeListener> listeners = new HashSet<ChangeListener>(1); // or can use ChangeSupport in NB 6.0
/** /**
* Adds a listener to changes of the panel's validity. * Adds a change listener to this panel.
* *
* @param l the change listener to add * @param listener The change listener to add.
*/ */
@Override @Override
public final void addChangeListener(ChangeListener l) { public final void addChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.add(l); listeners.add(listener);
} }
} }
/** /**
* Removes a listener to changes of the panel's validity. * Removes a change listener from this panel.
* *
* @param l the change listener to move * @param listener The change listener to remove.
*/ */
@Override @Override
public final void removeChangeListener(ChangeListener l) { public final void removeChangeListener(ChangeListener listener) {
synchronized (listeners) { synchronized (listeners) {
listeners.remove(l); listeners.remove(listener);
} }
} }
/** /**
* This method is auto-generated. It seems that this method is used to * Notifies any registerd change listeners of a change in the panel.
* listen to any change in this wizard panel.
*/ */
protected final void fireChangeEvent() { protected final void fireChangeEvent() {
Iterator<ChangeListener> it; Iterator<ChangeListener> it;
@ -138,10 +114,6 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
} }
} }
// You can use a settings object to keep track of state. Normally the
// settings object will be the WizardDescriptor, so you can use
// WizardDescriptor.getProperty & putProperty to store information entered
// by the user.
/** /**
* Provides the wizard panel with the current data--either the default data * Provides the wizard panel with the current data--either the default data
* or already-modified settings, if the user used the previous and/or next * or already-modified settings, if the user used the previous and/or next
@ -152,10 +124,6 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
*/ */
@Override @Override
public void readSettings(WizardDescriptor settings) { public void readSettings(WizardDescriptor settings) {
caseName = (String) settings.getProperty("caseName"); //NON-NLS
caseDir = (String) settings.getProperty("caseParentDir"); //NON-NLS
createdDirectory = (String) settings.getProperty("createdDirectory"); //NON-NLS
caseType = CaseType.values()[(int) settings.getProperty("caseType")]; //NON-NLS
} }
/** /**

View File

@ -100,9 +100,9 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
if (casePaths.length < 1) { if (casePaths.length < 1) {
return; return;
} }
final String casePath = casePaths[imagesTable.getSelectedRow()]; final String caseMetadataFilePath = casePaths[imagesTable.getSelectedRow()];
final String caseName = caseNames[imagesTable.getSelectedRow()]; final String caseName = caseNames[imagesTable.getSelectedRow()];
if (!casePath.isEmpty()) { if (!caseMetadataFilePath.isEmpty()) {
try { try {
StartupWindowProvider.getInstance().close(); StartupWindowProvider.getInstance().close();
CueBannerPanel.closeOpenRecentCasesWindow(); CueBannerPanel.closeOpenRecentCasesWindow();
@ -113,25 +113,27 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
/* /*
* Open the case. * Open the case.
*/ */
if (caseName.isEmpty() || casePath.isEmpty() || (!new File(casePath).exists())) { if (caseName.isEmpty() || caseMetadataFilePath.isEmpty() || (!new File(caseMetadataFilePath).exists())) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName), NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
JOptionPane.ERROR_MESSAGE); JOptionPane.ERROR_MESSAGE);
RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore RecentCases.getInstance().removeRecentCase(caseName, caseMetadataFilePath); // remove the recent case if it doesn't exist anymore
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
} else { } else {
new Thread(() -> { new Thread(() -> {
try { try {
Case.openAsCurrentCase(casePath); Case.openAsCurrentCase(caseMetadataFilePath);
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog( if (!(ex instanceof CaseActionCancelledException)) {
WindowManager.getDefault().getMainWindow(), logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
ex.getMessage(), // Should be user-friendly JOptionPane.showMessageDialog(
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS WindowManager.getDefault().getMainWindow(),
JOptionPane.ERROR_MESSAGE); ex.getMessage(),
NbBundle.getMessage(OpenRecentCasePanel.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
}
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}); });
} }

View File

@ -407,9 +407,11 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
String[] casePaths = new String[LENGTH]; String[] casePaths = new String[LENGTH];
String currentCasePath = null; String currentCasePath = null;
try { try {
currentCasePath = Case.getCurrentCase().getCaseMetadata().getFilePath().toString(); currentCasePath = Case.getCurrentCase().getMetadata().getFilePath().toString();
} catch (IllegalStateException ex) { } catch (IllegalStateException ex) {
// in case there is no current case. /*
* There may be no current case.
*/
} }
Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator(); Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator();

View File

@ -64,14 +64,17 @@ class RecentItems implements ActionListener {
new Thread(() -> { new Thread(() -> {
try { try {
Case.openAsCurrentCase(caseMetaDataFilePath); Case.openAsCurrentCase(caseMetaDataFilePath);
StartupWindowProvider.getInstance().close();
} catch (CaseActionException ex) { } catch (CaseActionException ex) {
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
JOptionPane.showMessageDialog( if (!(ex instanceof CaseActionCancelledException)) {
WindowManager.getDefault().getMainWindow(), logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
ex.getMessage(), JOptionPane.showMessageDialog(
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS WindowManager.getDefault().getMainWindow(),
JOptionPane.ERROR_MESSAGE); ex.getMessage(),
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
JOptionPane.ERROR_MESSAGE);
}
StartupWindowProvider.getInstance().open(); StartupWindowProvider.getInstance().open();
}); });
} }

View File

@ -204,8 +204,8 @@ public class SingleUserCaseConverter {
icd.getNewCaseName(), icd.getNewCaseName(),
icd.getNewCaseName(), icd.getNewCaseName(),
oldCaseMetadata.getCaseNumber(), oldCaseMetadata.getCaseNumber(),
oldCaseMetadata.getExaminer(), oldCaseMetadata.getExaminer());
dbName); newCaseMetadata.setCaseDatabaseName(dbName);
// Set created date. This calls writefile, no need to call it again // Set created date. This calls writefile, no need to call it again
newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate()); newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate());
newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion()); newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion());

View File

@ -26,9 +26,12 @@ import java.awt.Graphics;
import java.awt.dnd.DnDConstants; import java.awt.dnd.DnDConstants;
import java.awt.event.MouseAdapter; import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent; import java.awt.event.MouseEvent;
import java.beans.FeatureDescriptor;
import java.beans.PropertyChangeEvent;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -36,6 +39,8 @@ import java.util.Set;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.prefs.Preferences; import java.util.prefs.Preferences;
import java.util.stream.Stream; import java.util.stream.Stream;
import java.util.TreeSet;
import java.util.prefs.Preferences;
import javax.swing.JTable; import javax.swing.JTable;
import javax.swing.ListSelectionModel; import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
@ -44,6 +49,8 @@ import javax.swing.event.ListSelectionEvent;
import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelEvent;
import javax.swing.event.TableColumnModelListener; import javax.swing.event.TableColumnModelListener;
import javax.swing.table.TableCellRenderer; import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import org.netbeans.swing.etable.ETableColumn; import org.netbeans.swing.etable.ETableColumn;
import org.netbeans.swing.outline.DefaultOutlineCellRenderer; import org.netbeans.swing.outline.DefaultOutlineCellRenderer;
import org.netbeans.swing.outline.DefaultOutlineModel; import org.netbeans.swing.outline.DefaultOutlineModel;
@ -96,6 +103,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
// the column started and where it ended up. // the column started and where it ended up.
private int startColumnIndex = -1; private int startColumnIndex = -1;
private int endColumnIndex = -1; private int endColumnIndex = -1;
private OutlineView ov;
/* /*
* Convience reference to internal Outline. * Convience reference to internal Outline.
@ -125,8 +133,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
initComponents(); initComponents();
outlineView.setAllowedDragActions(DnDConstants.ACTION_NONE); outlineView.setAllowedDragActions(DnDConstants.ACTION_NONE);
outline = outlineView.getOutline();
outline = outlineView.getOutline();
outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
outline.setRootVisible(false); // don't show the root node outline.setRootVisible(false); // don't show the root node
outline.setDragEnabled(false); outline.setDragEnabled(false);
@ -334,7 +342,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
@Override @Override
@ThreadConfined(type = ThreadConfined.ThreadType.AWT) @ThreadConfined(type = ThreadConfined.ThreadType.AWT)
public void setNode(Node selectedNode) { public void setNode(Node selectedNode) {
/* /*
* The quick filter must be reset because when determining column width, * The quick filter must be reset because when determining column width,
* ETable.getRowCount is called, and the documentation states that quick * ETable.getRowCount is called, and the documentation states that quick
@ -406,14 +413,15 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
// Get the columns setup with respect to names and sortability // Get the columns setup with respect to names and sortability
String[] propStrings = new String[props.size() * 2]; String[] propStrings = new String[props.size() * 2];
for (int i = 0; i < props.size(); i++) { for (int i = 0; i < props.size(); i++) {
props.get(i).setValue("ComparableColumnTTV", Boolean.TRUE); //NON-NLS final Property<?> prop = props.get(i);
prop.setValue("ComparableColumnTTV", Boolean.TRUE); //NON-NLS
//First property column is sorted initially //First property column is sorted initially
if (i == 0) { if (i == 0) {
props.get(i).setValue("TreeColumnTTV", Boolean.TRUE); // Identifies special property representing first (tree) column. NON-NLS prop.setValue("TreeColumnTTV", Boolean.TRUE); // Identifies special property representing first (tree) column. NON-NLS
props.get(i).setValue("SortingColumnTTV", Boolean.TRUE); // TreeTableView should be initially sorted by this property column. NON-NLS prop.setValue("SortingColumnTTV", Boolean.TRUE); // TreeTableView should be initially sorted by this property column. NON-NLS
} }
propStrings[2 * i] = props.get(i).getName(); propStrings[2 * i] = prop.getName();
propStrings[2 * i + 1] = props.get(i).getDisplayName(); propStrings[2 * i + 1] = prop.getDisplayName();
} }
outlineView.setPropertyColumns(propStrings); outlineView.setPropertyColumns(propStrings);
@ -474,25 +482,44 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
// Store the current order of the columns into settings // Store the current order of the columns into settings
for (Map.Entry<Integer, Property<?>> entry : propertiesMap.entrySet()) { for (Map.Entry<Integer, Property<?>> entry : propertiesMap.entrySet()) {
preferences.put(getColumnPositionKey(tfn, entry.getValue().getName()), String.valueOf(entry.getKey()));
}
int numCols = outline.getColumnModel().getColumnCount(); preferences.put(getColumnPositionKey(tfn.getColumnOrderKey(), entry.getValue().getName()), String.valueOf(entry.getKey()));
}
final TableColumnModel columnModel = ov.getOutline().getColumnModel();
//store the sorting information
int numCols = columnModel.getColumnCount();
for (int i = 0; i < numCols; i++) { for (int i = 0; i < numCols; i++) {
ETableColumn etc = (ETableColumn) outline.getColumnModel().getColumn(i); ETableColumn etc = (ETableColumn) columnModel.getColumn(i);
String columnName = ov.getOutline().getColumnName(i);
if (etc.isSorted()) { if (etc.isSorted()) {
preferences.put(getColumnSortOrderKey(tfn, etc.getIdentifier().toString()), String.valueOf(etc.isAscending())); preferences.put(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.isAscending()));
preferences.put(getColumnSortRankKey(tfn, etc.getIdentifier().toString()), String.valueOf(etc.getSortRank())); preferences.put(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.getSortRank()));
preferences.put(getColumnSortOrderKey(tfn, etc.getIdentifier().toString()), String.valueOf(etc.isAscending()));
preferences.put(getColumnSortRankKey(tfn, etc.getIdentifier().toString()), String.valueOf(etc.getSortRank()));
} else { } else {
preferences.remove(getColumnSortOrderKey(tfn, etc.getIdentifier().toString())); preferences.remove(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName));
preferences.remove(getColumnSortRankKey(tfn, etc.getIdentifier().toString())); preferences.remove(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName));
} }
} }
} }
} }
static private final class ColumnSortInfo {
private final int modelIndex;
private final int rank;
private final boolean order;
private ColumnSortInfo(int modelIndex, int rank, boolean order) {
this.modelIndex = modelIndex;
this.rank = rank;
this.order = order;
}
private int getRank() {
return rank;
}
}
private synchronized void loadSort() { private synchronized void loadSort() {
if (currentRoot == null || propertiesMap.isEmpty()) { if (currentRoot == null || propertiesMap.isEmpty()) {
return; return;
@ -502,23 +529,29 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
TableFilterNode tfn = (TableFilterNode) currentRoot; TableFilterNode tfn = (TableFilterNode) currentRoot;
Map<Integer, Boolean> orderMap = new TreeMap<>(); if (currentRoot instanceof TableFilterNode) {
Map<Integer, Integer> indexMap = new TreeMap<>(); final String columnOrderKey = ((TableFilterNode) currentRoot).getColumnOrderKey();
propertiesMap.entrySet().forEach((entry) -> { final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
Boolean sortOrder = Boolean.valueOf(preferences.get(getColumnSortOrderKey(tfn, entry.getValue().getName()), "true"));
Integer sortRank = Integer.valueOf(preferences.get(getColumnSortRankKey(tfn, entry.getValue().getName()), "0"));
//if the sort rank is undefined, it will be defaulted to 0 , unsorted.
orderMap.put(sortRank, sortOrder); //organize property sorting information, sorted by rank
indexMap.put(sortRank, outline.getColumn(entry.getValue().getName()).getModelIndex()); TreeSet<ColumnSortInfo> treeSet = new TreeSet<>(Comparator.comparing(ColumnSortInfo::getRank));
}); propertiesMap.entrySet().stream()
.forEach(entry -> {
final String propName = entry.getValue().getName();
//if the sort rank is undefined, it will be defaulted to 0 => unsorted.
Integer sortRank = Integer.valueOf(preferences.get(getColumnSortRankKey(columnOrderKey, propName), "0"));
//default to true => ascending
Boolean sortOrder = Boolean.valueOf(preferences.get(getColumnSortOrderKey(columnOrderKey, propName), "true"));
treeSet.add(new ColumnSortInfo(entry.getKey(), sortRank, sortOrder));
});
//apply sort information in rank order.
treeSet.forEach(sortInfo -> ov.getOutline().setColumnSorted(sortInfo.modelIndex, sortInfo.order, sortInfo.rank));
}
orderMap.entrySet().forEach((entry) -> {
outline.setColumnSorted(indexMap.get(entry.getKey()), orderMap.get(entry.getKey()), entry.getKey());
});
} }
} }
/** /**
@ -547,8 +580,9 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
boolean noPreviousSettings = true; boolean noPreviousSettings = true;
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class); final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
for (Property<?> prop : props) { for (Property<?> prop : props) {
Integer value = Integer.valueOf(preferences.get(getColumnPositionKey(tfn, prop.getName()), "-1")); Integer value = Integer.valueOf(preferences.get(getColumnPositionKey(tfn.getColumnOrderKey(), prop.getName()), "-1"));
if (value >= 0 && value < offset && !propertiesMap.containsKey(value)) { if (value >= 0 && value < offset && !propertiesMap.containsKey(value)) {
propertiesMap.put(value, prop); propertiesMap.put(value, prop);
noPreviousSettings = false; noPreviousSettings = false;
@ -574,29 +608,29 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
* Gets a key for the current node and a property of its child nodes to * Gets a key for the current node and a property of its child nodes to
* store the column position into a preference file. * store the column position into a preference file.
* *
* @param propName Property of the column * @param prop Property of the column
* @param node The current node to use as a base for the property key. * @param type The type of the current node
* *
* @return A generated key for the preference file * @return A generated key for the preference file
*/ */
private String getColumnPositionKey(TableFilterNode node, String propName) { private String getColumnPositionKey(String type, String propName) {
return getColumnKeyBase(node, propName) + ".column"; //NON-NLS return getColumnKeyBase(type, propName) + ".column";
} }
private String getColumnSortOrderKey(TableFilterNode node, String propName) { private String getColumnSortOrderKey(String type, String propName) {
return getColumnKeyBase(node, propName) + ".sortOrder";//NON-NLS return getColumnKeyBase(type, propName) + ".sortOrder";
} }
private String getColumnSortRankKey(TableFilterNode node, String propName) { private String getColumnSortRankKey(String type, String propName) {
return getColumnKeyBase(node, propName) + ".sortRank";//NON-NLS return getColumnKeyBase(type, propName) + ".sortRank";
} }
private static String getColumnKeyBase(TableFilterNode node, String propName) { private static String getColumnKeyBase(String type, String propName) {
return stripNonAlphanumeric(node.getColumnOrderKey()) + "." + stripNonAlphanumeric(propName); return stripNonAlphanumeric(type) + "." + stripNonAlphanumeric(propName);
} }
private static String stripNonAlphanumeric(String str) { private static String stripNonAlphanumeric(String str) {
return str.replaceAll("[^a-zA-Z0-9_]", "");//NON-NLS return str.replaceAll("[^a-zA-Z0-9_]", "");
} }
@Override @Override

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 - 2016 Basis Technology Corp. * Copyright 2011 - 2017 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");
@ -156,6 +156,8 @@ public interface DisplayableItemNodeVisitor<T> {
T visit(EmptyNode.MessageNode emptyNode); T visit(EmptyNode.MessageNode emptyNode);
T visit(InterestingHits.InterestingItemTypeNode aThis);
/** /**
* Visitor with an implementable default behavior for all types. Override * Visitor with an implementable default behavior for all types. Override
* specific visit types to not use the default behavior. * specific visit types to not use the default behavior.
@ -238,6 +240,11 @@ public interface DisplayableItemNodeVisitor<T> {
return defaultVisit(ftByMimeTypeEmptyNode); return defaultVisit(ftByMimeTypeEmptyNode);
} }
@Override
public T visit(InterestingHits.InterestingItemTypeNode interestingItemTypeNode) {
return defaultVisit(interestingItemTypeNode);
}
@Override @Override
public T visit(DeletedContentNode dcn) { public T visit(DeletedContentNode dcn) {
return defaultVisit(dcn); return defaultVisit(dcn);

View File

@ -453,7 +453,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
* @return query.toString - portion of SQL query which will follow a * @return query.toString - portion of SQL query which will follow a
* WHERE clause. * WHERE clause.
*/ */
private String createQuery(String mime_type) { private String createQuery(String mimeType) {
StringBuilder query = new StringBuilder(); StringBuilder query = new StringBuilder();
query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS query.append("(dir_type = ").append(TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue()).append(")"); //NON-NLS
query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS query.append(" AND (type IN (").append(TskData.TSK_DB_FILES_TYPE_ENUM.FS.ordinal()).append(","); //NON-NLS
@ -466,7 +466,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
if (UserPreferences.hideKnownFilesInViewsTree()) { if (UserPreferences.hideKnownFilesInViewsTree()) {
query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS query.append(" AND (known IS NULL OR known != ").append(TskData.FileKnown.KNOWN.getFileKnownValue()).append(")"); //NON-NLS
} }
query.append(" AND mime_type = '").append(mime_type).append("'"); //NON-NLS query.append(" AND mime_type = '").append(mimeType).append("'"); //NON-NLS
return query.toString(); return query.toString();
} }

View File

@ -379,9 +379,10 @@ public class HashsetHits implements AutopsyVisitableItem {
hashsetResults.getArtifactIds(hashsetName).forEach((id) -> { hashsetResults.getArtifactIds(hashsetName).forEach((id) -> {
try { try {
BlackboardArtifact art = skCase.getBlackboardArtifact(id); if (!artifactHits.containsKey(id)) {
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
artifactHits.put(id, art); artifactHits.put(id, art);
}
list.add(id); list.add(id);
} catch (TskException ex) { } catch (TskException ex) {
logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2015 Basis Technology Corp. * Copyright 2011-2017 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");
@ -66,7 +66,7 @@ public class InterestingHits implements AutopsyVisitableItem {
private class InterestingResults extends Observable { private class InterestingResults extends Observable {
// NOTE: the map can be accessed by multiple worker threads and needs to be synchronized // NOTE: the map can be accessed by multiple worker threads and needs to be synchronized
private final Map<String, Set<Long>> interestingItemsMap = new LinkedHashMap<>(); private final Map<String, Map<String, Set<Long>>> interestingItemsMap = new LinkedHashMap<>();
public List<String> getSetNames() { public List<String> getSetNames() {
List<String> setNames; List<String> setNames;
@ -77,9 +77,9 @@ public class InterestingHits implements AutopsyVisitableItem {
return setNames; return setNames;
} }
public Set<Long> getArtifactIds(String setName) { public Set<Long> getArtifactIds(String setName, String typeName) {
synchronized (interestingItemsMap) { synchronized (interestingItemsMap) {
return interestingItemsMap.get(setName); return interestingItemsMap.get(setName).get(typeName);
} }
} }
@ -118,9 +118,11 @@ public class InterestingHits implements AutopsyVisitableItem {
String value = resultSet.getString("value_text"); //NON-NLS String value = resultSet.getString("value_text"); //NON-NLS
long artifactId = resultSet.getLong("artifact_id"); //NON-NLS long artifactId = resultSet.getLong("artifact_id"); //NON-NLS
if (!interestingItemsMap.containsKey(value)) { if (!interestingItemsMap.containsKey(value)) {
interestingItemsMap.put(value, new HashSet<>()); interestingItemsMap.put(value, new LinkedHashMap<>());
interestingItemsMap.get(value).put(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getDisplayName(), new HashSet<>());
interestingItemsMap.get(value).put(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName(), new HashSet<>());
} }
interestingItemsMap.get(value).add(artifactId); interestingItemsMap.get(value).get(artType.getDisplayName()).add(artifactId);
} }
} }
} catch (TskCoreException | SQLException ex) { } catch (TskCoreException | SQLException ex) {
@ -280,7 +282,7 @@ public class InterestingHits implements AutopsyVisitableItem {
private final String setName; private final String setName;
public SetNameNode(String setName) {//, Set<Long> children) { public SetNameNode(String setName) {//, Set<Long> children) {
super(Children.create(new HitFactory(setName), true), Lookups.singleton(setName)); super(Children.create(new HitTypeFactory(setName), true), Lookups.singleton(setName));
this.setName = setName; this.setName = setName;
super.setName(setName); super.setName(setName);
updateDisplayName(); updateDisplayName();
@ -289,12 +291,14 @@ public class InterestingHits implements AutopsyVisitableItem {
} }
private void updateDisplayName() { private void updateDisplayName() {
super.setDisplayName(setName + " (" + interestingResults.getArtifactIds(setName).size() + ")"); int sizeOfSet = interestingResults.getArtifactIds(setName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName()).size()
+ interestingResults.getArtifactIds(setName, BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getDisplayName()).size();
super.setDisplayName(setName + " (" + sizeOfSet + ")");
} }
@Override @Override
public boolean isLeafTypeNode() { public boolean isLeafTypeNode() {
return true; return false;
} }
@Override @Override
@ -334,14 +338,104 @@ public class InterestingHits implements AutopsyVisitableItem {
} }
} }
private class HitTypeFactory extends ChildFactory<String> implements Observer {
private final String setName;
private final Map<Long, BlackboardArtifact> artifactHits = new HashMap<>();
private HitTypeFactory(String setName) {
super();
this.setName = setName;
interestingResults.addObserver(this);
}
@Override
protected boolean createKeys(List<String> list) {
list.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getDisplayName());
list.add(BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName());
return true;
}
@Override
protected Node createNodeForKey(String key) {
return new InterestingItemTypeNode(setName, key);
}
@Override
public void update(Observable o, Object arg) {
refresh(true);
}
}
public class InterestingItemTypeNode extends DisplayableItemNode implements Observer {
private final String typeName;
private final String setName;
private InterestingItemTypeNode(String setName, String typeName) {
super(Children.create(new HitFactory(setName, typeName), true), Lookups.singleton(setName));
this.typeName = typeName;
this.setName = setName;
super.setName(typeName);
updateDisplayName();
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/interesting_item.png"); //NON-NLS
interestingResults.addObserver(this);
}
private void updateDisplayName() {
super.setDisplayName(typeName + " (" + interestingResults.getArtifactIds(setName, typeName).size() + ")");
}
@Override
public boolean isLeafTypeNode() {
return true;
}
@Override
protected Sheet createSheet() {
Sheet s = super.createSheet();
Sheet.Set ss = s.get(Sheet.PROPERTIES);
if (ss == null) {
ss = Sheet.createPropertiesSet();
s.put(ss);
}
ss.put(new NodeProperty<>(NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.name"),
NbBundle.getMessage(this.getClass(), "InterestingHits.createSheet.name.desc"),
getName()));
return s;
}
@Override
public <T> T accept(DisplayableItemNodeVisitor<T> v) {
return v.visit(this);
}
@Override
public void update(Observable o, Object arg) {
updateDisplayName();
}
@Override
public String getItemType() {
/**
* For custom settings for each rule set, return
* getClass().getName() + setName instead.
*/
return getClass().getName();
}
}
private class HitFactory extends ChildFactory<Long> implements Observer { private class HitFactory extends ChildFactory<Long> implements Observer {
private final String setName; private final String setName;
private Map<Long, BlackboardArtifact> artifactHits = new HashMap<>(); private final String typeName;
private final Map<Long, BlackboardArtifact> artifactHits = new HashMap<>();
private HitFactory(String setName) { private HitFactory(String setName, String typeName) {
super(); super();
this.setName = setName; this.setName = setName;
this.typeName = typeName;
interestingResults.addObserver(this); interestingResults.addObserver(this);
} }
@ -349,14 +443,15 @@ public class InterestingHits implements AutopsyVisitableItem {
protected boolean createKeys(List<Long> list) { protected boolean createKeys(List<Long> list) {
if (skCase == null) { if (skCase == null) {
return true; return true;
} }
interestingResults.getArtifactIds(setName).forEach((id) -> { interestingResults.getArtifactIds(setName, typeName).forEach((id) -> {
try { try {
BlackboardArtifact art = skCase.getBlackboardArtifact(id); if (!artifactHits.containsKey(id)) {
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
artifactHits.put(id, art); artifactHits.put(id, art);
}
list.add(id); list.add(id);
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS

View File

@ -707,14 +707,17 @@ public class KeywordHits implements AutopsyVisitableItem {
if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) { if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) {
for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME) ) { for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME) ) {
RegExpInstanceKey key = new RegExpInstanceKey(id); RegExpInstanceKey key = new RegExpInstanceKey(id);
nodesMap.put(key, createNode(key)); if (!nodesMap.containsKey(key)) {
nodesMap.put(key, createNode(key));
}
list.add(key); list.add(key);
} }
} else { } else {
for (String instance : instances) { for (String instance : instances) {
RegExpInstanceKey key = new RegExpInstanceKey(instance); RegExpInstanceKey key = new RegExpInstanceKey(instance);
nodesMap.put(key, createNode(key)); if (!nodesMap.containsKey(key)) {
nodesMap.put(key, createNode(key));
}
list.add(key); list.add(key);
} }
@ -897,11 +900,12 @@ public class KeywordHits implements AutopsyVisitableItem {
@Override @Override
protected boolean createKeys(List<Long> list) { protected boolean createKeys(List<Long> list) {
list.addAll(keywordResults.getArtifactIds(setName, keyword, instance));
for (Long id : keywordResults.getArtifactIds(setName, keyword, instance) ) { for (Long id : keywordResults.getArtifactIds(setName, keyword, instance) ) {
if (!nodesMap.containsKey(id)) {
nodesMap.put(id, createBlackboardArtifactNode(id)); nodesMap.put(id, createBlackboardArtifactNode(id));
list.add(id);
} }
list.add(id);
}
return true; return true;
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.datasourceprocessors;
import java.nio.file.Path; import java.nio.file.Path;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor; import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;

View File

@ -28,26 +28,27 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
/** /**
* A Raw data source processor that implements the DataSourceProcessor service * A Raw data source processor that implements the DataSourceProcessor service
* provider interface to allow integration with the add data source wizard. * provider interface to allow integration with the add data source wizard. It
* It also provides a run method overload to allow it to be used independently * also provides a run method overload to allow it to be used independently of
* of the wizard. * the wizard.
*/ */
@ServiceProvider(service = DataSourceProcessor.class) @ServiceProvider(service = DataSourceProcessor.class)
public class RawDSProcessor implements DataSourceProcessor { public class RawDSProcessor implements DataSourceProcessor {
private final RawDSInputPanel configPanel; private final RawDSInputPanel configPanel;
private AddRawImageTask addImageTask; private AddRawImageTask addImageTask;
/* /*
* Constructs a Raw data source processor that implements the * Constructs a Raw data source processor that implements the
* DataSourceProcessor service provider interface to allow integration * DataSourceProcessor service provider interface to allow integration with
* with the add data source wizard. It also provides a run method * the add data source wizard. It also provides a run method overload to
* overload to allow it to be used independently of the wizard. * allow it to be used independently of the wizard.
*/ */
public RawDSProcessor() { public RawDSProcessor() {
configPanel = RawDSInputPanel.createInstance(RawDSProcessor.class.getName()); configPanel = RawDSInputPanel.createInstance(RawDSProcessor.class.getName());
} }
/** /**
* Gets a string that describes the type of data sources this processor is * Gets a string that describes the type of data sources this processor is
* able to add to the case database. The string is suitable for display in a * able to add to the case database. The string is suitable for display in a
* type selection UI component (e.g., a combo box). * type selection UI component (e.g., a combo box).
@ -68,7 +69,7 @@ public class RawDSProcessor implements DataSourceProcessor {
*/ */
@Override @Override
public String getDataSourceType() { public String getDataSourceType() {
return Bundle.RawDSProcessor_dataSourceType(); return Bundle.RawDSProcessor_dataSourceType();
} }
/** /**
@ -119,28 +120,32 @@ public class RawDSProcessor implements DataSourceProcessor {
} }
/** /**
* Adds a data source to the case database using a background task in a * Adds a "raw" data source to the case database using a background task in
* separate thread and the given settings instead of those provided by the * a separate thread and the given settings instead of those provided by the
* selection and configuration panel. Returns as soon as the background task * selection and configuration panel. Returns as soon as the background task
* is started and uses the callback object to signal task completion and * is started and uses the callback object to signal task completion and
* return results. * return results.
* *
* @param deviceId An ASCII-printable identifier for the * @param deviceId An ASCII-printable identifier for the device
* device associated with the data source * associated with the data source that is
* that is intended to be unique across * intended to be unique across multiple cases
* multiple cases (e.g., a UUID). * (e.g., a UUID).
* @param rawDSInputFilePath Path to a Raw data source file. * @param imageFilePath Path to the image file.
* @param isHandsetFile Indicates whether the XML file is for a * @param timeZone The time zone to use when processing dates
* handset or a SIM. * and times for the image, obtained from
* @param progressMonitor Progress monitor for reporting progress * java.util.TimeZone.getID.
* during processing. * @param chunkSize The maximum size of each chunk of the raw
* data source as it is divided up into virtual
* unallocated space files.
* @param progressMonitor Progress monitor for reporting progress
* during processing.
* @param callback Callback to call when processing is done.
*/ */
private void run(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) { private void run(String deviceId, String imageFilePath, String timeZone, long chunkSize, DataSourceProcessorProgressMonitor progressMonitor, DataSourceProcessorCallback callback) {
addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback); addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback);
new Thread(addImageTask).start(); new Thread(addImageTask).start();
} }
@Override @Override
public void cancel() { public void cancel() {
} }

View File

@ -71,8 +71,9 @@ import org.sleuthkit.datamodel.TskException;
import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.VirtualDirectory;
/** /**
* This class wraps nodes as they are passed to the DataResult viewers. It * A node used to wrap another node before passing it to the result viewers. The
* defines the actions that the node should have. * wrapper node defines the actions associated with the wrapped node and may
* filter out some of its children.
*/ */
public class DataResultFilterNode extends FilterNode { public class DataResultFilterNode extends FilterNode {
@ -111,22 +112,33 @@ public class DataResultFilterNode extends FilterNode {
private final ExplorerManager sourceEm; private final ExplorerManager sourceEm;
/** /**
* Constructs a node used to wrap another node before passing it to the
* result viewers. The wrapper node defines the actions associated with the
* wrapped node and may filter out some of its children.
* *
* @param node Root node to be passed to DataResult viewers * @param node The node to wrap.
* @param em ExplorerManager for component that is creating the node * @param em The ExplorerManager for the component that is creating the
* node.
*/ */
public DataResultFilterNode(Node node, ExplorerManager em) { public DataResultFilterNode(Node node, ExplorerManager em) {
super(node, new DataResultFilterChildren(node, em)); super(node, new DataResultFilterChildren(node, em));
this.sourceEm = em; this.sourceEm = em;
} }
/** /**
* Constructs a node used to wrap another node before passing it to the
* result viewers. The wrapper node defines the actions associated with the
* wrapped node and may filter out some of its children.
* *
* @param node Root node to be passed to DataResult viewers * @param node The node to wrap.
* @param em ExplorerManager for component that is creating the node * @param em The ExplorerManager for the component that is creating
* the node.
* @param filterKnown Whether or not to filter out children that represent
* known files.
* @param filterSlack Whether or not to filter out children that represent
* virtual slack space files.
*/ */
private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) { private DataResultFilterNode(Node node, ExplorerManager em, boolean filterKnown, boolean filterSlack) {
super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack)); super(node, new DataResultFilterChildren(node, em, filterKnown, filterSlack));
this.sourceEm = em; this.sourceEm = em;
} }
@ -201,9 +213,9 @@ public class DataResultFilterNode extends FilterNode {
* DataResultFilterNode that created in the DataResultFilterNode.java. * DataResultFilterNode that created in the DataResultFilterNode.java.
* *
*/ */
private static class DataResultFilterChildren extends FilterNode.Children { private static class DataResultFilterChildren extends FilterNode.Children {
private final ExplorerManager sourceEm; private final ExplorerManager sourceEm;
private boolean filterKnown; private boolean filterKnown;
private boolean filterSlack; private boolean filterSlack;
@ -211,7 +223,7 @@ public class DataResultFilterNode extends FilterNode {
/** /**
* the constructor * the constructor
*/ */
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) { private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
super(arg); super(arg);
switch (SelectionContext.getSelectionContext(arg)) { switch (SelectionContext.getSelectionContext(arg)) {
case DATA_SOURCES: case DATA_SOURCES:
@ -230,7 +242,7 @@ public class DataResultFilterNode extends FilterNode {
this.sourceEm = sourceEm; this.sourceEm = sourceEm;
} }
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack) { private DataResultFilterChildren(Node arg, ExplorerManager sourceEm, boolean filterKnown, boolean filterSlack) {
super(arg); super(arg);
this.filterKnown = filterKnown; this.filterKnown = filterKnown;
this.filterSlack = filterSlack; this.filterSlack = filterSlack;
@ -326,9 +338,9 @@ public class DataResultFilterNode extends FilterNode {
actionsList.add(AddContentTagAction.getInstance()); actionsList.add(AddContentTagAction.getInstance());
actionsList.add(AddBlackboardArtifactTagAction.getInstance()); actionsList.add(AddBlackboardArtifactTagAction.getInstance());
final Collection<AbstractFile> selectedFilesList = final Collection<AbstractFile> selectedFilesList
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class)); = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
if(selectedFilesList.size() == 1) { if (selectedFilesList.size() == 1) {
actionsList.add(DeleteFileContentTagAction.getInstance()); actionsList.add(DeleteFileContentTagAction.getInstance());
} }
} else { } else {
@ -338,13 +350,13 @@ public class DataResultFilterNode extends FilterNode {
actionsList.add(AddBlackboardArtifactTagAction.getInstance()); actionsList.add(AddBlackboardArtifactTagAction.getInstance());
} }
final Collection<BlackboardArtifact> selectedArtifactsList = final Collection<BlackboardArtifact> selectedArtifactsList
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class)); = new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
if(selectedArtifactsList.size() == 1) { if (selectedArtifactsList.size() == 1) {
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance()); actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
} }
if(n != null) { if (n != null) {
actionsList.addAll(ContextMenuExtensionPoint.getActions()); actionsList.addAll(ContextMenuExtensionPoint.getActions());
} }
@ -362,7 +374,6 @@ public class DataResultFilterNode extends FilterNode {
return defaultVisit(fileTypes); return defaultVisit(fileTypes);
} }
@Override @Override
protected List<Action> defaultVisit(DisplayableItemNode ditem) { protected List<Action> defaultVisit(DisplayableItemNode ditem) {
//preserve the default node's actions //preserve the default node's actions
@ -460,8 +471,6 @@ public class DataResultFilterNode extends FilterNode {
return openChild(fileTypes); return openChild(fileTypes);
} }
/** /**
* Tell the originating ExplorerManager to display the given * Tell the originating ExplorerManager to display the given
* dataModelNode. * dataModelNode.

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011 Basis Technology Corp. * Copyright 2011-2017 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,15 +56,15 @@ import org.sleuthkit.datamodel.VolumeSystem;
* the DataResultViewer. 3. Waits for all the Children to be contentNode in the * the DataResultViewer. 3. Waits for all the Children to be contentNode in the
* DataResultViewer and selects the Node that represents the Content. * DataResultViewer and selects the Node that represents the Content.
*/ */
public class ViewContextAction extends AbstractAction { public final class ViewContextAction extends AbstractAction {
private Content content; private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(ViewContextAction.class.getName()); private static final Logger logger = Logger.getLogger(ViewContextAction.class.getName());
private Content content;
public ViewContextAction(String title, BlackboardArtifactNode node) { public ViewContextAction(String title, BlackboardArtifactNode node) {
super(title); super(title);
this.content = node.getLookup().lookup(Content.class); this.content = node.getLookup().lookup(Content.class);
} }
public ViewContextAction(String title, AbstractFsContentNode<? extends AbstractFile> node) { public ViewContextAction(String title, AbstractFsContentNode<? extends AbstractFile> node) {
@ -79,65 +79,70 @@ public class ViewContextAction extends AbstractAction {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(() -> {
@Override // create a list of Content objects starting with content's
public void run() { // Image and ends with content
// create a list of Content objects starting with content's ReverseHierarchyVisitor vtor = new ReverseHierarchyVisitor();
// Image and ends with content List<Content> hierarchy = content.accept(vtor);
ReverseHierarchyVisitor vtor = new ReverseHierarchyVisitor(); Collections.reverse(hierarchy);
List<Content> hierarchy = content.accept(vtor);
Collections.reverse(hierarchy);
Node generated = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(hierarchy)), true); Node generated = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(hierarchy)), true);
Children genChilds = generated.getChildren(); Children genChilds = generated.getChildren();
final DirectoryTreeTopComponent dirTree = DirectoryTreeTopComponent.findInstance(); final DirectoryTreeTopComponent dirTree = DirectoryTreeTopComponent.findInstance();
TreeView dirTreeView = dirTree.getTree(); TreeView dirTreeView = dirTree.getTree();
ExplorerManager dirTreeExplorerManager = dirTree.getExplorerManager(); ExplorerManager dirTreeExplorerManager = dirTree.getExplorerManager();
Node dirTreeRootNode = dirTreeExplorerManager.getRootContext(); Node dirTreeRootNode = dirTreeExplorerManager.getRootContext();
Children dirChilds = dirTreeRootNode.getChildren(); Children dirChilds = dirTreeRootNode.getChildren();
Children currentChildren = dirChilds.findChild(DataSourcesNode.NAME).getChildren(); Children currentChildren = dirChilds.findChild(DataSourcesNode.NAME).getChildren();
Node dirExplored = null; Node dirExplored = null;
// Find the parent node of the content in the directory tree // Find the parent node of the content in the directory tree
for (int i = 0; i < genChilds.getNodesCount() - 1; i++) { for (int i = 0; i < genChilds.getNodesCount() - 1; i++) {
Node currentGeneratedNode = genChilds.getNodeAt(i); Node currentGeneratedNode = genChilds.getNodeAt(i);
for (int j = 0; j < currentChildren.getNodesCount(); j++) { for (int j = 0; j < currentChildren.getNodesCount(); j++) {
Node currentDirectoryTreeNode = currentChildren.getNodeAt(j); Node currentDirectoryTreeNode = currentChildren.getNodeAt(j);
if (currentGeneratedNode.getDisplayName().equals(currentDirectoryTreeNode.getDisplayName())) { if (currentGeneratedNode.getDisplayName().equals(currentDirectoryTreeNode.getDisplayName())) {
dirExplored = currentDirectoryTreeNode; dirExplored = currentDirectoryTreeNode;
dirTreeView.expandNode(dirExplored);
currentChildren = currentDirectoryTreeNode.getChildren();
break;
}
}
}
// Set the parent node of the content as the selection in the
// directory tree
try {
if (dirExplored != null) {
dirTreeView.expandNode(dirExplored); dirTreeView.expandNode(dirExplored);
dirTreeExplorerManager.setExploredContextAndSelection(dirExplored, new Node[]{dirExplored}); currentChildren = currentDirectoryTreeNode.getChildren();
break;
} }
} catch (PropertyVetoException ex) {
logger.log(Level.WARNING, "Couldn't set selected node", ex); //NON-NLS
} }
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
DataResultTopComponent dataResultTC = dirTree.getDirectoryListing();
Node currentRootNodeOfDataResultTC = dataResultTC.getRootNode();
Node contentNode = content.accept(new RootContentChildren.CreateSleuthkitNodeVisitor());
new SelectionWorker(dataResultTC, contentNode.getName(), currentRootNodeOfDataResultTC).execute();
}
});
} }
// Set the parent node of the content as the selection in the
// directory tree
try {
if (dirExplored != null) {
dirTreeView.expandNode(dirExplored);
dirTreeExplorerManager.setExploredContextAndSelection(dirExplored, new Node[]{dirExplored});
}
} catch (PropertyVetoException ex) {
logger.log(Level.WARNING, "Couldn't set selected node", ex); //NON-NLS
}
EventQueue.invokeLater(() -> {
DataResultTopComponent dataResultTC = dirTree.getDirectoryListing();
Node currentRootNodeOfDataResultTC = dataResultTC.getRootNode();
Node contentNode = content.accept(new RootContentChildren.CreateSleuthkitNodeVisitor());
new SelectionWorker(dataResultTC, contentNode.getName(), currentRootNodeOfDataResultTC).execute();
});
}); });
} }
@Override
public Object clone() throws CloneNotSupportedException {
ViewContextAction clone = (ViewContextAction)super.clone();
clone.setContent(this.content);
return clone;
}
private void setContent(Content content) {
this.content = content;
}
/** /**
* Waits for a Node's children to be generated, regardless of whether they * Waits for a Node's children to be generated, regardless of whether they
* are lazily loaded, then sets the correct selection in a specified * are lazily loaded, then sets the correct selection in a specified
@ -215,14 +220,14 @@ public class ViewContextAction extends AbstractAction {
*/ */
private class ReverseHierarchyVisitor extends ContentVisitor.Default<List<Content>> { private class ReverseHierarchyVisitor extends ContentVisitor.Default<List<Content>> {
List<Content> ret = new ArrayList<Content>(); List<Content> ret = new ArrayList<>();
private List<Content> visitParentButDontAddMe(Content content) { private List<Content> visitParentButDontAddMe(Content content) {
Content parent = null; Content parent = null;
try { try {
parent = content.getParent(); parent = content.getParent();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Couldn't get parent of Content object: " + content); //NON-NLS logger.log(Level.WARNING, "Could not get parent of Content object: {0}", content); //NON-NLS
} }
return parent == null ? ret : parent.accept(this); return parent == null ? ret : parent.accept(this);
} }
@ -234,7 +239,7 @@ public class ViewContextAction extends AbstractAction {
try { try {
parent = content.getParent(); parent = content.getParent();
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.WARNING, "Couldn't get parent of Content object: " + content); //NON-NLS logger.log(Level.WARNING, "Could not get parent of Content object: {0}", content); //NON-NLS
} }
return parent == null ? ret : parent.accept(this); return parent == null ? ret : parent.accept(this);
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 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");
@ -25,19 +25,15 @@ import org.openide.DialogDisplayer;
import org.openide.NotifyDescriptor; import org.openide.NotifyDescriptor;
import org.openide.util.NbBundle; import org.openide.util.NbBundle;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.openide.util.lookup.ServiceProviders; import org.sleuthkit.autopsy.appservices.AutopsyService;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.framework.AutopsyService;
@ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)})
/** /**
* Creates and handles closing of ImageWriter objects. * Creates and handles closing of ImageWriter objects. Currently, ImageWriter is
* Currently, ImageWriter is only enabled for local disks, and local disks can * only enabled for local disks, and local disks can not be processed in multi
* not be processed in multi user mode. If ImageWriter is ever enabled for multi user * user mode. If ImageWriter is ever enabled for multi user cases this code will
* cases this code will need to be revised. * need to be revised.
*/ */
@ServiceProvider(service = AutopsyService.class)
public class ImageWriterService implements AutopsyService { public class ImageWriterService implements AutopsyService {
private static final List<ImageWriter> imageWriters = new ArrayList<>(); // Contains all Image Writer objects private static final List<ImageWriter> imageWriters = new ArrayList<>(); // Contains all Image Writer objects
@ -45,14 +41,16 @@ public class ImageWriterService implements AutopsyService {
/** /**
* Create an image writer object for the given data source ID. * Create an image writer object for the given data source ID.
* @param imageId ID for the image *
* @param imageId ID for the image.
* @param settings Image writer settings to be used when writing the image.
*/ */
public static void createImageWriter(Long imageId, ImageWriterSettings settings){ public static void createImageWriter(Long imageId, ImageWriterSettings settings) {
// ImageWriter objects are created during the addImageTask. They can not arrive while // ImageWriter objects are created during the addImageTask. They can not arrive while
// we're closing case resources so we don't need to worry about one showing up while // we're closing case resources so we don't need to worry about one showing up while
// doing our close/cleanup. // doing our close/cleanup.
synchronized(imageWritersLock){ synchronized (imageWritersLock) {
ImageWriter writer = new ImageWriter(imageId, settings); ImageWriter writer = new ImageWriter(imageId, settings);
writer.subscribeToEvents(); writer.subscribeToEvents();
imageWriters.add(writer); imageWriters.add(writer);
@ -66,54 +64,58 @@ public class ImageWriterService implements AutopsyService {
@Override @Override
public void closeCaseResources(CaseContext context) throws AutopsyServiceException { public void closeCaseResources(CaseContext context) throws AutopsyServiceException {
context.getProgressIndicator().progress(NbBundle.getMessage(this.getClass(), "ImageWriterService.waitingForVHDs")); synchronized (imageWritersLock) {
if (imageWriters.isEmpty()) {
return;
}
context.getProgressIndicator().progress(NbBundle.getMessage(this.getClass(), "ImageWriterService.waitingForVHDs"));
synchronized(imageWritersLock){
// If any of our ImageWriter objects haven't started the finish task, set the cancel flag // If any of our ImageWriter objects haven't started the finish task, set the cancel flag
// to make sure they don't start now. The reason they haven't started is that // to make sure they don't start now. The reason they haven't started is that
// ingest was not complete, and the user already confirmed that they want to exit // ingest was not complete, and the user already confirmed that they want to exit
// even though ingest is not complete so we will take that to mean that they // even though ingest is not complete so we will take that to mean that they
// also don't want to wait for Image Writer. // also don't want to wait for Image Writer.
for(ImageWriter writer: imageWriters){ for (ImageWriter writer : imageWriters) {
writer.cancelIfNotStarted(); writer.cancelIfNotStarted();
} }
// Test whether any finishImage tasks are in progress // Test whether any finishImage tasks are in progress
boolean jobsAreInProgress = false; boolean jobsAreInProgress = false;
for(ImageWriter writer: imageWriters){ for (ImageWriter writer : imageWriters) {
if(writer.jobIsInProgress()){ if (writer.jobIsInProgress()) {
jobsAreInProgress = true; jobsAreInProgress = true;
break; break;
} }
} }
if(jobsAreInProgress){ if (jobsAreInProgress) {
// If jobs are in progress, ask the user if they want to wait for them to complete // If jobs are in progress, ask the user if they want to wait for them to complete
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation( NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
NbBundle.getMessage(this.getClass(), "ImageWriterService.shouldWait"), NbBundle.getMessage(this.getClass(), "ImageWriterService.shouldWait"),
NbBundle.getMessage(this.getClass(), "ImageWriterService.localDisk"), NbBundle.getMessage(this.getClass(), "ImageWriterService.localDisk"),
NotifyDescriptor.YES_NO_OPTION, NotifyDescriptor.YES_NO_OPTION,
NotifyDescriptor.WARNING_MESSAGE); NotifyDescriptor.WARNING_MESSAGE);
descriptor.setValue(NotifyDescriptor.NO_OPTION); descriptor.setValue(NotifyDescriptor.NO_OPTION);
Object response = DialogDisplayer.getDefault().notify(descriptor); Object response = DialogDisplayer.getDefault().notify(descriptor);
if(response == DialogDescriptor.NO_OPTION){ if (response == DialogDescriptor.NO_OPTION) {
// Cancel all the jobs // Cancel all the jobs
for(ImageWriter writer: imageWriters){ for (ImageWriter writer : imageWriters) {
writer.cancelJob(); writer.cancelJob();
} }
} }
// Wait for all finishImage jobs to complete. If the jobs got cancelled // Wait for all finishImage jobs to complete. If the jobs got cancelled
// this will be very fast. // this will be very fast.
for(ImageWriter writer: imageWriters){ for (ImageWriter writer : imageWriters) {
writer.waitForJobToFinish(); writer.waitForJobToFinish();
} }
} }
// Stop listening for events // Stop listening for events
for(ImageWriter writer: imageWriters){ for (ImageWriter writer : imageWriters) {
writer.unsubscribeFromEvents(); writer.unsubscribeFromEvents();
} }

View File

@ -393,6 +393,9 @@ public class IngestJobSettings {
/** /**
* Gets the module names for a given key within these ingest job settings. * Gets the module names for a given key within these ingest job settings.
* *
* @param context The identifier for the context for which to get the
* module names, e.g., the Add Data Source wizard or
* Run Ingest Modules context.
* @param key The key string. * @param key The key string.
* @param defaultSetting The default list of module names. * @param defaultSetting The default list of module names.
* *

View File

@ -138,9 +138,6 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
} }
/**
* @inheritDoc
*/
@Override @Override
public void addPropertyChangeListener(PropertyChangeListener l) { public void addPropertyChangeListener(PropertyChangeListener l) {
filterPanel.addPropertyChangeListener(l); filterPanel.addPropertyChangeListener(l);
@ -148,9 +145,6 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
profilePanel.addPropertyChangeListener(l); profilePanel.addPropertyChangeListener(l);
} }
/**
* @inheritDoc
*/
@Override @Override
public void removePropertyChangeListener(PropertyChangeListener l) { public void removePropertyChangeListener(PropertyChangeListener l) {
filterPanel.removePropertyChangeListener(l); filterPanel.removePropertyChangeListener(l);
@ -158,9 +152,6 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
profilePanel.removePropertyChangeListener(l); profilePanel.removePropertyChangeListener(l);
} }
/**
* @inheritDoc
*/
@Override @Override
public void saveSettings() { public void saveSettings() {
saveTabByIndex(tabbedPane.getSelectedIndex()); saveTabByIndex(tabbedPane.getSelectedIndex());
@ -189,17 +180,11 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
} }
} }
/**
* @inheritDoc
*/
@Override @Override
public void store() { public void store() {
saveSettings(); saveSettings();
} }
/**
* @inheritDoc
*/
@Override @Override
public void load() { public void load() {
filterPanel.load(); filterPanel.load();

View File

@ -40,9 +40,6 @@ public class IngestOptionsPanelController extends OptionsPanelController {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this); private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private boolean changed; private boolean changed;
/**
* @inheritDoc
*/
@Override @Override
public void update() { public void update() {
getPanel().load(); getPanel().load();
@ -69,9 +66,6 @@ public class IngestOptionsPanelController extends OptionsPanelController {
return panel; return panel;
} }
/**
* @inheritDoc
*/
@Override @Override
public void applyChanges() { public void applyChanges() {
if (changed) { if (changed) {
@ -85,57 +79,36 @@ public class IngestOptionsPanelController extends OptionsPanelController {
} }
} }
/**
* @inheritDoc
*/
@Override @Override
public void cancel() { public void cancel() {
getPanel().cancel(); getPanel().cancel();
} }
/**
* @inheritDoc
*/
@Override @Override
public boolean isValid() { public boolean isValid() {
return getPanel().valid(); return getPanel().valid();
} }
/**
* @inheritDoc
*/
@Override @Override
public boolean isChanged() { public boolean isChanged() {
return changed; return changed;
} }
/**
* @inheritDoc
*/
@Override @Override
public JComponent getComponent(Lookup lkp) { public JComponent getComponent(Lookup lkp) {
return getPanel(); return getPanel();
} }
/**
* @inheritDoc
*/
@Override @Override
public HelpCtx getHelpCtx() { public HelpCtx getHelpCtx() {
return null; return null;
} }
/**
* @inheritDoc
*/
@Override @Override
public void addPropertyChangeListener(PropertyChangeListener pl) { public void addPropertyChangeListener(PropertyChangeListener pl) {
pcs.addPropertyChangeListener(pl); pcs.addPropertyChangeListener(pl);
} }
/**
* @inheritDoc
*/
@Override @Override
public void removePropertyChangeListener(PropertyChangeListener pl) { public void removePropertyChangeListener(PropertyChangeListener pl) {
pcs.removePropertyChangeListener(pl); pcs.removePropertyChangeListener(pl);

View File

@ -43,7 +43,6 @@ public abstract class ShortcutWizardDescriptorPanel implements WizardDescriptor.
/** /**
* Whether or not the panel immediately following this one should be skipped * Whether or not the panel immediately following this one should be skipped
* .
* *
* @return true or false * @return true or false
*/ */

View File

@ -21,19 +21,24 @@ package org.sleuthkit.autopsy.modules.embeddedfileextractor;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.lang.IllegalArgumentException;
import java.lang.IndexOutOfBoundsException;
import java.lang.NullPointerException;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import org.apache.poi.OldFileFormatException;
import org.apache.poi.POIXMLException; import org.apache.poi.POIXMLException;
import org.apache.poi.hslf.model.Picture; import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hslf.usermodel.PictureData; import org.apache.poi.hslf.usermodel.HSLFPictureData;
import org.apache.poi.hslf.usermodel.SlideShow; import org.apache.poi.hslf.usermodel.HSLFSlideShow;
import org.apache.poi.hssf.record.RecordInputStream.LeftoverDataException;
import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument; import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.model.PicturesTable; import org.apache.poi.hwpf.model.PicturesTable;
import org.apache.poi.sl.usermodel.PictureData.PictureType;
import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.util.RecordFormatException;
import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XMLSlideShow;
import org.apache.poi.xslf.usermodel.XSLFPictureData; import org.apache.poi.xslf.usermodel.XSLFPictureData;
import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.apache.poi.xssf.usermodel.XSSFWorkbook;
@ -209,20 +214,31 @@ class ImageExtractor {
* extracted. * extracted.
*/ */
private List<ExtractedImage> extractImagesFromDoc(AbstractFile af) { private List<ExtractedImage> extractImagesFromDoc(AbstractFile af) {
List<org.apache.poi.hwpf.usermodel.Picture> listOfAllPictures; List<Picture> listOfAllPictures;
try { try {
HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af)); HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af));
PicturesTable pictureTable = doc.getPicturesTable(); PicturesTable pictureTable = doc.getPicturesTable();
listOfAllPictures = pictureTable.getAllPictures(); listOfAllPictures = pictureTable.getAllPictures();
} catch (OldFileFormatException | IOException ex) { } catch (IOException | IllegalArgumentException |
// OldFileFormatException: IndexOutOfBoundsException | NullPointerException ex) {
// Thrown when the document version is unsupported (Word 95 and
// older)
// IOException: // IOException:
// Thrown when the document has issues being read. // Thrown when the document has issues being read.
// IllegalArgumentException:
// This will catch OldFileFormatException, which is thrown when the
// document's format is Word 95 or older. Alternatively, this is
// thrown when attempting to load an RTF file as a DOC file.
// However, our code verifies the file format before ever running it
// through the ImageExtractor. This exception gets thrown in the
// "IN10-0137.E01" image regardless. The reason is unknown.
// IndexOutOfBoundsException:
// NullPointerException:
// These get thrown in certain images. The reason is unknown. It is
// likely due to problems with the file formats that POI is poorly
// handling.
return null; return null;
} catch (Throwable ex) { } catch (Throwable ex) {
// instantiating POI containers throw RuntimeExceptions // instantiating POI containers throw RuntimeExceptions
@ -241,7 +257,7 @@ class ImageExtractor {
} }
List<ExtractedImage> listOfExtractedImages = new ArrayList<>(); List<ExtractedImage> listOfExtractedImages = new ArrayList<>();
byte[] data = null; byte[] data = null;
for (org.apache.poi.hwpf.usermodel.Picture picture : listOfAllPictures) { for (Picture picture : listOfAllPictures) {
String fileName = picture.suggestFullFileName(); String fileName = picture.suggestFullFileName();
try { try {
data = picture.getContent(); data = picture.getContent();
@ -319,17 +335,25 @@ class ImageExtractor {
* extracted. * extracted.
*/ */
private List<ExtractedImage> extractImagesFromPpt(AbstractFile af) { private List<ExtractedImage> extractImagesFromPpt(AbstractFile af) {
PictureData[] listOfAllPictures = null; List<HSLFPictureData> listOfAllPictures = null;
try { try {
SlideShow ppt = new SlideShow(new ReadContentInputStream(af)); HSLFSlideShow ppt = new HSLFSlideShow(new ReadContentInputStream(af));
listOfAllPictures = ppt.getPictureData(); listOfAllPictures = ppt.getPictureData();
} catch (OldFileFormatException | IOException ex) { } catch (IOException | IllegalArgumentException |
// OldFileFormatException: IndexOutOfBoundsException ex) {
// Thrown when the document version is unsupported // IllegalArgumentException:
// This will catch OldFileFormatException, which is thrown when the
// document version is unsupported. The IllegalArgumentException may
// also get thrown for unknown reasons.
// IOException: // IOException:
// Thrown when the document has issues being read // Thrown when the document has issues being read.
// IndexOutOfBoundsException:
// This gets thrown in certain images. The reason is unknown. It is
// likely due to problems with the file formats that POI is poorly
// handling.
return null; return null;
} catch (Throwable ex) { } catch (Throwable ex) {
@ -341,7 +365,7 @@ class ImageExtractor {
// if no images are extracted from the PPT, return null, else initialize // if no images are extracted from the PPT, return null, else initialize
// the output folder for image extraction. // the output folder for image extraction.
String outputFolderPath; String outputFolderPath;
if (listOfAllPictures.length == 0) { if (listOfAllPictures.isEmpty()) {
return null; return null;
} else { } else {
outputFolderPath = getOutputFolderPath(this.parentFileName); outputFolderPath = getOutputFolderPath(this.parentFileName);
@ -355,26 +379,26 @@ class ImageExtractor {
int i = 0; int i = 0;
List<ExtractedImage> listOfExtractedImages = new ArrayList<>(); List<ExtractedImage> listOfExtractedImages = new ArrayList<>();
byte[] data = null; byte[] data = null;
for (PictureData pictureData : listOfAllPictures) { for (HSLFPictureData pictureData : listOfAllPictures) {
// Get image extension, generate image name, write image to the module // Get image extension, generate image name, write image to the module
// output folder, add it to the listOfExtractedImageAbstractFiles // output folder, add it to the listOfExtractedImageAbstractFiles
int type = pictureData.getType(); PictureType type = pictureData.getType();
String ext; String ext;
switch (type) { switch (type) {
case Picture.JPEG: case JPEG:
ext = ".jpg"; //NON-NLS ext = ".jpg"; //NON-NLS
break; break;
case Picture.PNG: case PNG:
ext = ".png"; //NON-NLS ext = ".png"; //NON-NLS
break; break;
case Picture.WMF: case WMF:
ext = ".wmf"; //NON-NLS ext = ".wmf"; //NON-NLS
break; break;
case Picture.EMF: case EMF:
ext = ".emf"; //NON-NLS ext = ".emf"; //NON-NLS
break; break;
case Picture.PICT: case PICT:
ext = ".pict"; //NON-NLS ext = ".pict"; //NON-NLS
break; break;
default: default:
@ -406,7 +430,7 @@ class ImageExtractor {
try { try {
XMLSlideShow pptx = new XMLSlideShow(new ReadContentInputStream(af)); XMLSlideShow pptx = new XMLSlideShow(new ReadContentInputStream(af));
listOfAllPictures = pptx.getAllPictures(); listOfAllPictures = pptx.getPictureData();
} catch (POIXMLException | IOException ex) { } catch (POIXMLException | IOException ex) {
// POIXMLException: // POIXMLException:
// Thrown when document fails to load. // Thrown when document fails to load.
@ -468,12 +492,30 @@ class ImageExtractor {
try { try {
Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af)); Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af));
listOfAllPictures = xls.getAllPictures(); listOfAllPictures = xls.getAllPictures();
} catch (OldFileFormatException | IOException ex) { } catch (IOException | LeftoverDataException |
// OldFileFormatException: RecordFormatException | IllegalArgumentException |
// Thrown when the document version is unsupported IndexOutOfBoundsException ex) {
// IllegalArgumentException:
// This will catch OldFileFormatException, which is thrown when the
// document version is unsupported. The IllegalArgumentException may
// also get thrown for unknown reasons.
// IOException: // IOException:
// Thrown when the document has issues being read // Thrown when the document has issues being read.
// LeftoverDataException:
// This is thrown for poorly formatted files that have more data
// than expected.
// RecordFormatException:
// This is thrown for poorly formatted files that have less data
// that expected.
// IllegalArgumentException:
// IndexOutOfBoundsException:
// These get thrown in certain images. The reason is unknown. It is
// likely due to problems with the file formats that POI is poorly
// handling.
return null; return null;
} catch (Throwable ex) { } catch (Throwable ex) {

View File

@ -169,9 +169,6 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
this.equalitySignComboBox.setSelectedIndex(2); this.equalitySignComboBox.setSelectedIndex(2);
} }
/**
* @inheritDoc
*/
@Override @Override
public void saveSettings() { public void saveSettings() {
try { try {
@ -203,17 +200,11 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
ingestWarningLabel.setVisible(!isEnabled); ingestWarningLabel.setVisible(!isEnabled);
} }
/**
* @inheritDoc
*/
@Override @Override
public void store() { public void store() {
this.saveSettings(); this.saveSettings();
} }
/**
* @inheritDoc
*/
@Override @Override
public void load() { public void load() {
this.resetComponents(); this.resetComponents();

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.progress;
import java.util.logging.Level; import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
@ -59,7 +59,7 @@ public final class LoggingProgressIndicator implements ProgressIndicator {
@Override @Override
public void progress(int workUnitsCompleted) { public void progress(int workUnitsCompleted) {
LOGGER.log(Level.INFO, "{1} of {2} total work units completed", new Object[]{workUnitsCompleted, this.totalWorkUnits}); LOGGER.log(Level.INFO, "{0} of {1} total work units completed", new Object[]{workUnitsCompleted, this.totalWorkUnits});
} }
@Override @Override
@ -68,8 +68,8 @@ public final class LoggingProgressIndicator implements ProgressIndicator {
} }
@Override @Override
public void finish(String message) { public void finish() {
LOGGER.log(Level.INFO, "{0} finished", message); LOGGER.log(Level.INFO, "Finished");
} }
} }

View File

@ -16,11 +16,13 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.progress;
import java.awt.Dialog; import java.awt.Dialog;
import java.awt.Frame; import java.awt.Frame;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import javax.annotation.concurrent.GuardedBy;
import javax.annotation.concurrent.ThreadSafe;
import javax.swing.JDialog; import javax.swing.JDialog;
import javax.swing.SwingUtilities; import javax.swing.SwingUtilities;
import org.openide.DialogDescriptor; import org.openide.DialogDescriptor;
@ -30,14 +32,21 @@ import org.openide.util.HelpCtx;
/** /**
* A progress indicator that displays progress using a modal dialog with a * A progress indicator that displays progress using a modal dialog with a
* message label, a progress bar, and optionally, a configurable set of buttons * message label, a progress bar, and optionally, a configurable set of buttons
* with a button listener. * with a button listener. Setting a cancelling flag which locks in a cancelling
* message and an indeterminate progress bar is supported.
*/ */
@ThreadSafe
public final class ModalDialogProgressIndicator implements ProgressIndicator { public final class ModalDialogProgressIndicator implements ProgressIndicator {
private final Frame parent; private final Frame parent;
private final String title;
private final ProgressPanel progressPanel; private final ProgressPanel progressPanel;
private final Dialog dialog; private final Object[] buttonLabels;
private final Object focusedButtonLabel;
private final ActionListener buttonListener; private final ActionListener buttonListener;
private Dialog dialog;
@GuardedBy("this")
private boolean cancelling;
/** /**
* Creates a progress indicator that displays progress using a modal dialog * Creates a progress indicator that displays progress using a modal dialog
@ -53,17 +62,11 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
*/ */
public ModalDialogProgressIndicator(Frame parent, String title, Object[] buttonLabels, Object focusedButtonLabel, ActionListener buttonListener) { public ModalDialogProgressIndicator(Frame parent, String title, Object[] buttonLabels, Object focusedButtonLabel, ActionListener buttonListener) {
this.parent = parent; this.parent = parent;
this.title = title;
progressPanel = new ProgressPanel(); progressPanel = new ProgressPanel();
DialogDescriptor dialogDescriptor = new DialogDescriptor( progressPanel.setIndeterminate(true);
progressPanel, this.buttonLabels = buttonLabels;
title, this.focusedButtonLabel = focusedButtonLabel;
true,
buttonLabels,
focusedButtonLabel,
DialogDescriptor.BOTTOM_ALIGN,
HelpCtx.DEFAULT_HELP,
buttonListener);
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
this.buttonListener = buttonListener; this.buttonListener = buttonListener;
} }
@ -76,32 +79,12 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
*/ */
public ModalDialogProgressIndicator(Frame parent, String title) { public ModalDialogProgressIndicator(Frame parent, String title) {
this.parent = parent; this.parent = parent;
this.title = title;
progressPanel = new ProgressPanel(); progressPanel = new ProgressPanel();
dialog = new JDialog(parent, title, true); progressPanel.setIndeterminate(true);
dialog.add(progressPanel); this.buttonLabels = null;
dialog.pack(); this.focusedButtonLabel = null;
buttonListener = null; this.buttonListener = null;
}
/**
* Calls setVisible on the underlying modal dialog.
*
* @param isVisible True or false.
*/
public void setVisible(boolean isVisible) {
if (isVisible) {
dialog.setLocationRelativeTo(parent);
}
this.dialog.setVisible(isVisible);
}
/**
* Gets the button listener for the dialog, if there is one.
*
* @return The button listener or null.
*/
public ActionListener getButtonListener() {
return buttonListener;
} }
/** /**
@ -112,14 +95,13 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param totalWorkUnits The total number of work units. * @param totalWorkUnits The total number of work units.
*/ */
@Override @Override
public void start(String message, int totalWorkUnits) { public synchronized void start(String message, int totalWorkUnits) {
SwingUtilities.invokeLater(new Runnable() { cancelling = false;
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(false);
progressPanel.setInderminate(false); progressPanel.setMessage(message);
progressPanel.setMessage(message); progressPanel.setMaximum(totalWorkUnits);
progressPanel.setMaximum(totalWorkUnits); displayDialog();
}
}); });
} }
@ -130,13 +112,27 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param message The initial progress message. * @param message The initial progress message.
*/ */
@Override @Override
public void start(String message) { public synchronized void start(String message) {
SwingUtilities.invokeLater(new Runnable() { cancelling = false;
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(true);
progressPanel.setInderminate(true); progressPanel.setMessage(message);
progressPanel.setMessage(message); displayDialog();
} });
}
/**
* Sets a cancelling message and makes the progress bar indeterminate. Once
* cancel has been called, the progress indicator no longer accepts updates
* unless start is called again.
*
* @param cancellingMessage
*/
public synchronized void setCancelling(String cancellingMessage) {
cancelling = true;
SwingUtilities.invokeLater(() -> {
progressPanel.setIndeterminate(false);
progressPanel.setMessage(cancellingMessage);
}); });
} }
@ -147,14 +143,13 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param message The initial progress message. * @param message The initial progress message.
*/ */
@Override @Override
public void switchToIndeterminate(String message) { public synchronized void switchToIndeterminate(String message) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(true);
progressPanel.setInderminate(true);
progressPanel.setMessage(message); progressPanel.setMessage(message);
} });
}); }
} }
/** /**
@ -166,16 +161,15 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param totalWorkUnits The total number of work units to be completed. * @param totalWorkUnits The total number of work units to be completed.
*/ */
@Override @Override
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) { public synchronized void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() { progressPanel.setIndeterminate(false);
progressPanel.setInderminate(false);
progressPanel.setMessage(message); progressPanel.setMessage(message);
progressPanel.setMaximum(totalWorkUnits); progressPanel.setMaximum(totalWorkUnits);
progressPanel.setCurrent(workUnitsCompleted); progressPanel.setCurrent(workUnitsCompleted);
} });
}); }
} }
/** /**
@ -184,13 +178,12 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param message The progress message. * @param message The progress message.
*/ */
@Override @Override
public void progress(String message) { public synchronized void progress(String message) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() {
progressPanel.setMessage(message); progressPanel.setMessage(message);
} });
}); }
} }
/** /**
@ -201,13 +194,12 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param workUnitsCompleted Number of work units completed so far. * @param workUnitsCompleted Number of work units completed so far.
*/ */
@Override @Override
public void progress(int workUnitsCompleted) { public synchronized void progress(int workUnitsCompleted) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() {
progressPanel.setCurrent(workUnitsCompleted); progressPanel.setCurrent(workUnitsCompleted);
} });
}); }
} }
/** /**
@ -219,29 +211,52 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
* @param workUnitsCompleted Number of work units completed so far. * @param workUnitsCompleted Number of work units completed so far.
*/ */
@Override @Override
public void progress(String message, int workUnitsCompleted) { public synchronized void progress(String message, int workUnitsCompleted) {
SwingUtilities.invokeLater(new Runnable() { if (!cancelling) {
@Override SwingUtilities.invokeLater(() -> {
public void run() {
progressPanel.setMessage(message); progressPanel.setMessage(message);
progressPanel.setCurrent(workUnitsCompleted); progressPanel.setCurrent(workUnitsCompleted);
} });
}); }
} }
/** /**
* Finishes the progress indicator when the task is completed. * Finishes the progress indicator when the task is completed.
*
* @param message The finished message.
*/ */
@Override @Override
public void finish(String message) { public synchronized void finish() {
SwingUtilities.invokeLater(new Runnable() { SwingUtilities.invokeLater(() -> {
@Override this.dialog.setVisible(false);
public void run() {
progressPanel.setMessage(message);
}
}); });
} }
/**
* Creates and dislpays the dialog for the progress indicator.
*/
private void displayDialog() {
if (null != buttonLabels && null != focusedButtonLabel && null != buttonListener) {
/*
* Dialog with buttons.
*/
DialogDescriptor dialogDescriptor = new DialogDescriptor(
progressPanel,
title,
true,
buttonLabels,
focusedButtonLabel,
DialogDescriptor.BOTTOM_ALIGN,
HelpCtx.DEFAULT_HELP,
buttonListener);
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
} else {
/*
* Dialog without buttons.
*/
dialog = new JDialog(parent, title, true);
dialog.add(progressPanel);
dialog.pack();
}
dialog.setLocationRelativeTo(parent);
this.dialog.setVisible(true);
}
} }

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.progress;
/** /**
* An interface for progress indicators. A progress indicator can run in * An interface for progress indicators. A progress indicator can run in
@ -46,6 +46,7 @@ public interface ProgressIndicator {
/** /**
* Switches the progress indicator to indeterminate mode (the total number * Switches the progress indicator to indeterminate mode (the total number
* of work units to be completed is unknown). * of work units to be completed is unknown).
*
* @param message The initial progress message. * @param message The initial progress message.
*/ */
public void switchToIndeterminate(String message); public void switchToIndeterminate(String message);
@ -54,7 +55,7 @@ public interface ProgressIndicator {
* Switches the progress indicator to determinate mode (the total number of * Switches the progress indicator to determinate mode (the total number of
* work units to be completed is known). * work units to be completed is known).
* *
* @param message The initial progress message. * @param message The initial progress message.
* @param workUnitsCompleted The number of work units completed so far. * @param workUnitsCompleted The number of work units completed so far.
* @param totalWorkUnits The total number of work units to be completed. * @param totalWorkUnits The total number of work units to be completed.
*/ */
@ -88,9 +89,7 @@ public interface ProgressIndicator {
/** /**
* Finishes the progress indicator when the task is completed. * Finishes the progress indicator when the task is completed.
*
* @param message The finished message.
*/ */
void finish(String message); void finish();
} }

View File

@ -42,7 +42,7 @@
<Component class="javax.swing.JLabel" name="progressMessage"> <Component class="javax.swing.JLabel" name="progressMessage">
<Properties> <Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/framework/Bundle.properties" key="ProgressPanel.progressMessage.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/> <ResourceString bundle="org/sleuthkit/autopsy/progress/Bundle.properties" key="ProgressPanel.progressMessage.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property> </Property>
</Properties> </Properties>
</Component> </Component>

View File

@ -16,7 +16,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.progress;
/** /**
* A progress panel consisting of a message label and a progress bar. * A progress panel consisting of a message label and a progress bar.
@ -35,7 +35,7 @@ class ProgressPanel extends javax.swing.JPanel {
this.progressMessage.setText(message); this.progressMessage.setText(message);
} }
void setInderminate(boolean indeterminate) { void setIndeterminate(boolean indeterminate) {
this.progressBar.setIndeterminate(indeterminate); this.progressBar.setIndeterminate(indeterminate);
} }

View File

@ -16,9 +16,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.sleuthkit.autopsy.framework; package org.sleuthkit.autopsy.progress;
import org.sleuthkit.autopsy.framework.ProgressIndicator; import org.sleuthkit.autopsy.progress.ProgressIndicator;
/** /**
* A "silent" or "null" progress indicator. * A "silent" or "null" progress indicator.
@ -54,7 +54,7 @@ public class SilentProgressIndicator implements ProgressIndicator {
} }
@Override @Override
public void finish(String message) { public void finish() {
} }
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-2014 Basis Technology Corp. * Copyright 2013-2017 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");
@ -80,15 +80,15 @@ class ReportExcel implements TableReportModule {
Font titleFont = wb.createFont(); Font titleFont = wb.createFont();
titleFont.setFontHeightInPoints((short) 12); titleFont.setFontHeightInPoints((short) 12);
titleStyle.setFont(titleFont); titleStyle.setFont(titleFont);
titleStyle.setAlignment(CellStyle.ALIGN_LEFT); titleStyle.setAlignment(HorizontalAlignment.LEFT);
titleStyle.setWrapText(true); titleStyle.setWrapText(true);
setStyle = wb.createCellStyle(); setStyle = wb.createCellStyle();
Font setFont = wb.createFont(); Font setFont = wb.createFont();
setFont.setFontHeightInPoints((short) 14); setFont.setFontHeightInPoints((short) 14);
setFont.setBoldweight((short) 10); setFont.setBold(true);
setStyle.setFont(setFont); setStyle.setFont(setFont);
setStyle.setAlignment(CellStyle.ALIGN_LEFT); setStyle.setAlignment(HorizontalAlignment.LEFT);
setStyle.setWrapText(true); setStyle.setWrapText(true);
elementStyle = wb.createCellStyle(); elementStyle = wb.createCellStyle();
@ -96,7 +96,7 @@ class ReportExcel implements TableReportModule {
Font elementFont = wb.createFont(); Font elementFont = wb.createFont();
elementFont.setFontHeightInPoints((short) 14); elementFont.setFontHeightInPoints((short) 14);
elementStyle.setFont(elementFont); elementStyle.setFont(elementFont);
elementStyle.setAlignment(CellStyle.ALIGN_LEFT); elementStyle.setAlignment(HorizontalAlignment.LEFT);
elementStyle.setWrapText(true); elementStyle.setWrapText(true);
writeSummaryWorksheet(); writeSummaryWorksheet();

View File

@ -0,0 +1,126 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.test;
import java.util.logging.Level;
import org.openide.util.Exceptions;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.services.Blackboard;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.FileIngestModuleAdapter;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
/**
* A file ingest module that creates some interestng artifacts
* with attributes based on files for test purposes.
*/
final class InterestingArtifactCreatorIngestModule extends FileIngestModuleAdapter {
private static final Logger logger = Logger.getLogger(InterestingArtifactCreatorIngestModule.class.getName());
private static final String MODULE_NAME = InterestingArtifactCreatorIngestModuleFactory.getModuleName();
private static final String[] ARTIFACT_TYPE_NAMES = {"TSK_WEB_BOOKMARK", "TSK_KEYWORD_HIT", "TSK_CALLLOG"};
private static final String[] ARTIFACT_DISPLAY_NAMES = {"Web Bookmarks", "Keyword Hits", "Call Logs"};
private static final String INT_ARTIFACT_TYPE_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getLabel();
private static final String INT_ARTIFACT_DISPLAY_NAME = BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getDisplayName();
private BlackboardArtifact.Type artifactType;
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
try {
artifactType = blackboard.getOrAddArtifactType(INT_ARTIFACT_TYPE_NAME, INT_ARTIFACT_DISPLAY_NAME);
} catch (Blackboard.BlackboardException ex) {
throw new IngestModuleException(Bundle.ErrorCreatingCustomBlackBoardType(), ex);
}
}
@Override
public ProcessResult process(AbstractFile file) {
/*
* Skip directories and virtual files.
*/
if (file.isDir() || file.isVirtual()) {
return ProcessResult.OK;
}
try {
/*
* Add a custom artifact with one custom attribute of each value
* type.
*/
int randomArtIndex = (int) (Math.random() * 3);
Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
BlackboardArtifact.Type artifactTypeBase = blackboard.getOrAddArtifactType(ARTIFACT_TYPE_NAMES[randomArtIndex], ARTIFACT_DISPLAY_NAMES[randomArtIndex]);
BlackboardArtifact artifactBase = file.newArtifact(artifactTypeBase.getTypeID());
String commentTxt;
BlackboardAttribute baseAttr;
switch (artifactBase.getArtifactTypeID()) {
case 2:
commentTxt = "www.placeholderWebsiteDOTCOM";
baseAttr = new BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_URL, "Fake Web BookMark", "www.thisWebsiteIsStillFake.com");
artifactBase.addAttribute(baseAttr);
break;
case 9:
commentTxt = "fakeKeyword";
baseAttr = new BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, "Fake Keyword Search", "Fake Keyword Preview Text");
BlackboardAttribute set = new BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, "Fake Keyword Search", "Fake");
BlackboardAttribute keyword = new BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, "Fake Keyword Search", "FakeKeyword");
artifactBase.addAttribute(baseAttr);
artifactBase.addAttribute(set);
artifactBase.addAttribute(keyword);
break;
case 25:
commentTxt = "fake phone number from";
baseAttr = new BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, "Fake Call Log Whatever", "555-555-5555");
artifactBase.addAttribute(baseAttr);
break;
default:
commentTxt = "DEPENDENT ON ARTIFACT TYPE";
break;
}
BlackboardArtifact artifact = file.newArtifact(artifactType.getTypeID());
BlackboardAttribute att = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, "ArtifactsAndTxt");
BlackboardAttribute att2 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, commentTxt);
BlackboardAttribute att3 = new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, MODULE_NAME, "");
artifact.addAttribute(att);
artifact.addAttribute(att2);
artifact.addAttribute(att3);
artifact.addAttribute(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactBase.getArtifactID()));
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, String.format("Failed to process file (obj_id = %d)", file.getId()), ex);
return ProcessResult.ERROR;
} catch (Blackboard.BlackboardException ex) {
Exceptions.printStackTrace(ex);
}
return ProcessResult.OK;
}
}

View File

@ -0,0 +1,64 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2017 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.test;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.coreutils.Version;
import org.sleuthkit.autopsy.ingest.FileIngestModule;
import org.sleuthkit.autopsy.ingest.IngestModuleFactory;
import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter;
import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings;
/**
* A factory for file ingest modules that creates some interestng artifacts with
* attributes based on files for test purposes. Uncomment the service provider
* annotation to activate this test fixture.
*/
//@ServiceProvider(service = IngestModuleFactory.class)
public final class InterestingArtifactCreatorIngestModuleFactory extends IngestModuleFactoryAdapter {
@Override
public String getModuleDisplayName() {
return getModuleName();
}
@Override
public String getModuleDescription() {
return "Creates some interestng artifacts with attributes based on files for test purposes.";
}
@Override
public String getModuleVersionNumber() {
return Version.getVersion();
}
@Override
public boolean isFileIngestModuleFactory() {
return true;
}
@Override
public FileIngestModule createFileIngestModule(IngestModuleIngestJobSettings settings) {
return new InterestingArtifactCreatorIngestModule();
}
static String getModuleName() {
return "Test Interesting Artifact Creator";
}
}

View File

@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.test;
import java.util.logging.Level; import java.util.logging.Level;
import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.framework.AutopsyService; import org.sleuthkit.autopsy.appservices.AutopsyService;
import org.sleuthkit.autopsy.framework.ProgressIndicator; import org.sleuthkit.autopsy.progress.ProgressIndicator;
/** /**
* An implementation of the Autopsy service interface used for test purposes. * An implementation of the Autopsy service interface used for test purposes.
@ -53,7 +53,7 @@ public class TestAutopsyService implements AutopsyService {
progressIndicator.progress(80); progressIndicator.progress(80);
Thread.sleep(1000L); Thread.sleep(1000L);
progressIndicator.progress(100); progressIndicator.progress(100);
progressIndicator.finish("First task completed by Test Autopsy Service."); progressIndicator.finish();
progressIndicator.start("Test Autopsy Service doing second task..."); progressIndicator.start("Test Autopsy Service doing second task...");
for (int i = 0; i < 10000; ++i) { for (int i = 0; i < 10000; ++i) {
logger.log(Level.INFO, "Test Autopsy Service simulating work on second task"); logger.log(Level.INFO, "Test Autopsy Service simulating work on second task");
@ -62,7 +62,7 @@ public class TestAutopsyService implements AutopsyService {
break; break;
} }
} }
progressIndicator.finish("Second task completed by Test Autopsy Service."); progressIndicator.finish();
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
logger.log(Level.INFO, "Test Autopsy Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested()); logger.log(Level.INFO, "Test Autopsy Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested());
} }

View File

@ -100,11 +100,15 @@ public class EventRootNode extends DisplayableItemNode {
*/ */
if (eventIDs.size() < MAX_EVENTS_TO_DISPLAY) { if (eventIDs.size() < MAX_EVENTS_TO_DISPLAY) {
for (Long eventId: eventIDs){ for (Long eventId: eventIDs){
nodesMap.put(eventId, createNode(eventId)); if (!nodesMap.containsKey(eventId)) {
toPopulate.add(eventId); nodesMap.put(eventId, createNode(eventId));
}
toPopulate.add(eventId);
} }
} else { } else {
nodesMap.put(-1L, createNode(-1L)); if (!nodesMap.containsKey(-1L)) {
nodesMap.put(-1L, createNode(-1L));
}
toPopulate.add(-1L); toPopulate.add(-1L);
} }
return true; return true;

View File

@ -28,8 +28,8 @@
<dependency conf="autopsy_core->*" org="log4j" name="log4j" rev="1.2.17"/> <dependency conf="autopsy_core->*" org="log4j" name="log4j" rev="1.2.17"/>
<!-- <dependency conf="autopsy_core->*" org="org.jdom" name="jdom" rev="1.1.3"/> --> <!-- <dependency conf="autopsy_core->*" org="org.jdom" name="jdom" rev="1.1.3"/> -->
<dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-excelant" rev="3.8"/> <dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-excelant" rev="3.15"/>
<dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-scratchpad" rev="3.8"/> <dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-scratchpad" rev="3.15"/>
<!-- process and system monitoring, note: matching native libs pulled from thirdparty --> <!-- process and system monitoring, note: matching native libs pulled from thirdparty -->
<dependency conf="autopsy_core->*" org="org.fusesource" name="sigar" rev="1.6.4" /> <dependency conf="autopsy_core->*" org="org.fusesource" name="sigar" rev="1.6.4" />

View File

@ -6,7 +6,8 @@ file.reference.avalon-framework-4.1.5.jar=release/modules/ext/avalon-framework-4
file.reference.common-image-3.2.jar=release/modules/ext/common-image-3.2.jar file.reference.common-image-3.2.jar=release/modules/ext/common-image-3.2.jar
file.reference.common-io-3.2.jar=release/modules/ext/common-io-3.2.jar file.reference.common-io-3.2.jar=release/modules/ext/common-io-3.2.jar
file.reference.common-lang-3.2.jar=release/modules/ext/common-lang-3.2.jar file.reference.common-lang-3.2.jar=release/modules/ext/common-lang-3.2.jar
file.reference.commons-codec-1.5.jar=release/modules/ext/commons-codec-1.5.jar file.reference.commons-codec-1.10.jar=release/modules/ext/commons-codec-1.10.jar
file.reference.commons-collections4-4.1.jar=release/modules/ext/commons-collections4-4.1.jar
file.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4.jar file.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4.jar
file.reference.commons-io-2.4.jar=release/modules/ext/commons-io-2.4.jar file.reference.commons-io-2.4.jar=release/modules/ext/commons-io-2.4.jar
file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar file.reference.commons-lang-2.6.jar=release/modules/ext/commons-lang-2.6.jar
@ -56,11 +57,11 @@ file.reference.logkit-1.0.1.jar=release/modules/ext/logkit-1.0.1.jar
file.reference.mail-1.4.3.jar=release/modules/ext/mail-1.4.3.jar file.reference.mail-1.4.3.jar=release/modules/ext/mail-1.4.3.jar
file.reference.openjfx-dialogs-1.0.2.jar=release/modules/ext/openjfx-dialogs-1.0.3.jar file.reference.openjfx-dialogs-1.0.2.jar=release/modules/ext/openjfx-dialogs-1.0.3.jar
file.reference.platform-3.4.0.jar=release/modules/ext/platform-3.4.0.jar file.reference.platform-3.4.0.jar=release/modules/ext/platform-3.4.0.jar
file.reference.poi-3.8.jar=release/modules/ext/poi-3.8.jar file.reference.poi-3.15.jar=release/modules/ext/poi-3.15.jar
file.reference.poi-excelant-3.8.jar=release/modules/ext/poi-excelant-3.8.jar file.reference.poi-excelant-3.15.jar=release/modules/ext/poi-excelant-3.15.jar
file.reference.poi-ooxml-3.8.jar=release/modules/ext/poi-ooxml-3.8.jar file.reference.poi-ooxml-3.15.jar=release/modules/ext/poi-ooxml-3.15.jar
file.reference.poi-ooxml-schemas-3.8.jar=release/modules/ext/poi-ooxml-schemas-3.8.jar file.reference.poi-ooxml-schemas-3.15.jar=release/modules/ext/poi-ooxml-schemas-3.15.jar
file.reference.poi-scratchpad-3.8.jar=release/modules/ext/poi-scratchpad-3.8.jar file.reference.poi-scratchpad-3.15.jar=release/modules/ext/poi-scratchpad-3.15.jar
file.reference.reflections-0.9.8.jar=release/modules/ext/reflections-0.9.8.jar file.reference.reflections-0.9.8.jar=release/modules/ext/reflections-0.9.8.jar
file.reference.servlet-api-2.5.jar=release/modules/ext/servlet-api-2.5.jar file.reference.servlet-api-2.5.jar=release/modules/ext/servlet-api-2.5.jar
file.reference.sigar-1.6.4-sources.jar=release/modules/ext/sigar-1.6.4-sources.jar file.reference.sigar-1.6.4-sources.jar=release/modules/ext/sigar-1.6.4-sources.jar
@ -69,7 +70,7 @@ file.reference.slf4j-api-1.6.1.jar=release/modules/ext/slf4j-api-1.6.1.jar
file.reference.slf4j-simple-1.6.1.jar=release/modules/ext/slf4j-simple-1.6.1.jar file.reference.slf4j-simple-1.6.1.jar=release/modules/ext/slf4j-simple-1.6.1.jar
file.reference.stax-api-1.0.1.jar=release/modules/ext/stax-api-1.0.1.jar file.reference.stax-api-1.0.1.jar=release/modules/ext/stax-api-1.0.1.jar
file.reference.xml-apis-1.0.b2.jar=release/modules/ext/xml-apis-1.0.b2.jar file.reference.xml-apis-1.0.b2.jar=release/modules/ext/xml-apis-1.0.b2.jar
file.reference.xmlbeans-2.3.0.jar=release/modules/ext/xmlbeans-2.3.0.jar file.reference.xmlbeans-2.6.0.jar=release/modules/ext/xmlbeans-2.6.0.jar
javac.source=1.8 javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial javac.compilerargs=-Xlint -Xlint:-serial
javadoc.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-javadoc.jar javadoc.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-javadoc.jar

View File

@ -700,16 +700,16 @@
<binary-origin>release/modules/ext/sigar-1.6.4.jar</binary-origin> <binary-origin>release/modules/ext/sigar-1.6.4.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/xmlbeans-2.3.0.jar</runtime-relative-path> <runtime-relative-path>ext/xmlbeans-2.6.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlbeans-2.3.0.jar</binary-origin> <binary-origin>release/modules/ext/xmlbeans-2.6.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/jna-3.4.0.jar</runtime-relative-path> <runtime-relative-path>ext/jna-3.4.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jna-3.4.0.jar</binary-origin> <binary-origin>release/modules/ext/jna-3.4.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-ooxml-schemas-3.8.jar</runtime-relative-path> <runtime-relative-path>ext/poi-ooxml-schemas-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.8.jar</binary-origin> <binary-origin>release/modules/ext/poi-ooxml-schemas-3.15.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/gson-1.4.jar</runtime-relative-path> <runtime-relative-path>ext/gson-1.4.jar</runtime-relative-path>
@ -768,8 +768,8 @@
<binary-origin>release/modules/ext/jcalendarbutton-1.4.6.jar</binary-origin> <binary-origin>release/modules/ext/jcalendarbutton-1.4.6.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-ooxml-3.8.jar</runtime-relative-path> <runtime-relative-path>ext/poi-ooxml-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-ooxml-3.8.jar</binary-origin> <binary-origin>release/modules/ext/poi-ooxml-3.15.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/imageio-psd-3.2.jar</runtime-relative-path> <runtime-relative-path>ext/imageio-psd-3.2.jar</runtime-relative-path>
@ -779,13 +779,17 @@
<runtime-relative-path>ext/stax-api-1.0.1.jar</runtime-relative-path> <runtime-relative-path>ext/stax-api-1.0.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/stax-api-1.0.1.jar</binary-origin> <binary-origin>release/modules/ext/stax-api-1.0.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/commons-collections4-4.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-collections4-4.1.jar</binary-origin>
</class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/servlet-api-2.5.jar</runtime-relative-path> <runtime-relative-path>ext/servlet-api-2.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/servlet-api-2.5.jar</binary-origin> <binary-origin>release/modules/ext/servlet-api-2.5.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-excelant-3.8.jar</runtime-relative-path> <runtime-relative-path>ext/poi-excelant-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-excelant-3.8.jar</binary-origin> <binary-origin>release/modules/ext/poi-excelant-3.15.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/imageio-pcx-3.2.jar</runtime-relative-path> <runtime-relative-path>ext/imageio-pcx-3.2.jar</runtime-relative-path>
@ -824,8 +828,8 @@
<binary-origin>release/modules/ext/geronimo-jms_1.1_spec-1.0.jar</binary-origin> <binary-origin>release/modules/ext/geronimo-jms_1.1_spec-1.0.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-scratchpad-3.8.jar</runtime-relative-path> <runtime-relative-path>ext/poi-scratchpad-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-scratchpad-3.8.jar</binary-origin> <binary-origin>release/modules/ext/poi-scratchpad-3.15.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/joda-time-2.4-sources.jar</runtime-relative-path> <runtime-relative-path>ext/joda-time-2.4-sources.jar</runtime-relative-path>
@ -876,8 +880,8 @@
<binary-origin>release/modules/ext/ant-1.8.2.jar</binary-origin> <binary-origin>release/modules/ext/ant-1.8.2.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/commons-codec-1.5.jar</runtime-relative-path> <runtime-relative-path>ext/commons-codec-1.10.jar</runtime-relative-path>
<binary-origin>release/modules/ext/commons-codec-1.5.jar</binary-origin> <binary-origin>release/modules/ext/commons-codec-1.10.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/javassist-3.12.1.GA.jar</runtime-relative-path> <runtime-relative-path>ext/javassist-3.12.1.GA.jar</runtime-relative-path>
@ -896,8 +900,8 @@
<binary-origin>release/modules/ext/commons-io-2.4.jar</binary-origin> <binary-origin>release/modules/ext/commons-io-2.4.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/poi-3.8.jar</runtime-relative-path> <runtime-relative-path>ext/poi-3.15.jar</runtime-relative-path>
<binary-origin>release/modules/ext/poi-3.8.jar</binary-origin> <binary-origin>release/modules/ext/poi-3.15.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/controlsfx-8.40.11.jar</runtime-relative-path> <runtime-relative-path>ext/controlsfx-8.40.11.jar</runtime-relative-path>

View File

@ -7,7 +7,7 @@
</configurations> </configurations>
<dependencies> <dependencies>
<dependency conf="experimental->default" org="com.github.lgooddatepicker" name="LGoodDatePicker" rev="4.3.1"/> <dependency conf="experimental->default" org="com.github.lgooddatepicker" name="LGoodDatePicker" rev="4.3.1"/>
<dependency conf="experimental->default" org="org.apache.tika" name="tika-core" rev="1.5"/> <dependency conf="experimental->default" org="org.apache.tika" name="tika-core" rev="1.14"/>
<dependency conf="experimental->default" org="org.postgresql" name="postgresql" rev="9.4-1201-jdbc41"/> <dependency conf="experimental->default" org="org.postgresql" name="postgresql" rev="9.4-1201-jdbc41"/>
<dependency conf="experimental->default" org="com.mchange" name="c3p0" rev="0.9.5"/> <dependency conf="experimental->default" org="com.mchange" name="c3p0" rev="0.9.5"/>
<dependency conf="experimental->default" org="com.fasterxml.jackson.core" name="jackson-core" rev="2.7.0"/> <dependency conf="experimental->default" org="com.fasterxml.jackson.core" name="jackson-core" rev="2.7.0"/>

View File

@ -3,7 +3,7 @@ file.reference.jackson-core-2.7.0.jar=release/modules/ext/jackson-core-2.7.0.jar
file.reference.LGoodDatePicker-4.3.1.jar=release/modules/ext/LGoodDatePicker-4.3.1.jar file.reference.LGoodDatePicker-4.3.1.jar=release/modules/ext/LGoodDatePicker-4.3.1.jar
file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar file.reference.mchange-commons-java-0.2.9.jar=release/modules/ext/mchange-commons-java-0.2.9.jar
file.reference.postgresql-9.4-1201-jdbc41.jar=release/modules/ext/postgresql-9.4-1201-jdbc41.jar file.reference.postgresql-9.4-1201-jdbc41.jar=release/modules/ext/postgresql-9.4-1201-jdbc41.jar
file.reference.tika-core-1.5.jar=release/modules/ext/tika-core-1.5.jar file.reference.tika-core-1.14.jar=release/modules/ext/tika-core-1.14.jar
javac.source=1.8 javac.source=1.8
javac.compilerargs=-Xlint -Xlint:-serial javac.compilerargs=-Xlint -Xlint:-serial
javadoc.reference.LGoodDatePicker-4.3.1.jar=release/modules/ext/LGoodDatePicker-4.3.1-javadoc.jar javadoc.reference.LGoodDatePicker-4.3.1.jar=release/modules/ext/LGoodDatePicker-4.3.1-javadoc.jar

View File

@ -132,8 +132,8 @@
<binary-origin>release/modules/ext/LGoodDatePicker-4.3.1.jar</binary-origin> <binary-origin>release/modules/ext/LGoodDatePicker-4.3.1.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/tika-core-1.5.jar</runtime-relative-path> <runtime-relative-path>ext/tika-core-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/tika-core-1.5.jar</binary-origin> <binary-origin>release/modules/ext/tika-core-1.14.jar</binary-origin>
</class-path-extension> </class-path-extension>
<class-path-extension> <class-path-extension>
<runtime-relative-path>ext/jackson-core-2.7.0.jar</runtime-relative-path> <runtime-relative-path>ext/jackson-core-2.7.0.jar</runtime-relative-path>

View File

@ -39,10 +39,11 @@ import javax.swing.SwingWorker;
import javax.swing.event.ListSelectionEvent; import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableModel; import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn; import javax.swing.table.TableColumn;
import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.CaseActionCancelledException;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.casemodule.StartupWindowProvider; import org.sleuthkit.autopsy.casemodule.StartupWindowProvider;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
/** /**
* A panel that allows a user to open cases created by auto ingest. * A panel that allows a user to open cases created by auto ingest.
@ -295,18 +296,12 @@ public final class AutoIngestCasePanel extends JPanel {
protected void done() { protected void done() {
try { try {
get(); get();
} catch (InterruptedException ex) { } catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex); if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
ex.getMessage(), MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"), }
JOptionPane.ERROR_MESSAGE); StartupWindowProvider.getInstance().open();
} catch (ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error while opening case with case metadata file path %s", caseMetadataFilePath), ex);
JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(),
ex.getCause().getMessage(),
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"),
JOptionPane.ERROR_MESSAGE);
} finally { } finally {
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
} }

View File

@ -92,8 +92,8 @@ import static org.sleuthkit.autopsy.experimental.autoingest.ManifestNodeData.Pro
import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences; import org.sleuthkit.autopsy.experimental.configuration.AutoIngestUserPreferences;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration; import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration;
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException; import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException; import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
import org.sleuthkit.autopsy.ingest.IngestJob; import org.sleuthkit.autopsy.ingest.IngestJob;
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason; import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
import org.sleuthkit.autopsy.ingest.IngestJobSettings; import org.sleuthkit.autopsy.ingest.IngestJobSettings;

View File

@ -39,10 +39,10 @@ import org.xml.sax.SAXException;
public final class AutopsyManifestFileParser implements ManifestFileParser { public final class AutopsyManifestFileParser implements ManifestFileParser {
private static final String MANIFEST_FILE_NAME_SIGNATURE = "_Manifest.xml"; private static final String MANIFEST_FILE_NAME_SIGNATURE = "_Manifest.xml";
private static final String ROOT_ELEM_TAG_NAME = "Manifest"; private static final String ROOT_ELEM_TAG_NAME = "AutopsyManifest";
private static final String CASE_NAME_XPATH = "/Manifest/Collection/Name/text()"; private static final String CASE_NAME_XPATH = "/AutopsyManifest/CaseName/text()";
private static final String DEVICE_ID_XPATH = "/Manifest/Collection/Image/ID/text()"; private static final String DEVICE_ID_XPATH = "/AutopsyManifest/DeviceId/text()";
private static final String DATA_SOURCE_NAME_XPATH = "/Manifest/Collection/Image/Name/text()"; private static final String DATA_SOURCE_NAME_XPATH = "/AutopsyManifest/DataSource/text()";
@Override @Override
public boolean fileIsManifest(Path filePath) { public boolean fileIsManifest(Path filePath) {
@ -62,10 +62,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
@Override @Override
public Manifest parse(Path filePath) throws ManifestFileParserException { public Manifest parse(Path filePath) throws ManifestFileParserException {
if (!fileIsManifest(filePath)) {
throw new ManifestFileParserException(String.format("%s not recognized as a manifest", filePath));
}
try { try {
Document doc = this.createManifestDOM(filePath); Document doc = this.createManifestDOM(filePath);
XPath xpath = XPathFactory.newInstance().newXPath(); XPath xpath = XPathFactory.newInstance().newXPath();

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2015 Basis Technology Corp. * Copyright 2015-2017 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");
@ -20,9 +20,28 @@ package org.sleuthkit.autopsy.experimental.autoingest;
import java.nio.file.Path; import java.nio.file.Path;
/**
* Responsible for parsing the manifest files that
* describe cases, devices, and data sources.
* These are used by autoingest to create cases and add
* data sources to the correct case.
*/
public interface ManifestFileParser { public interface ManifestFileParser {
/**
* Checks if a file is this type of manifest file
* @param filePath Path to potential manifest file
* @return True if the file is a manifest that this parser supports
*/
boolean fileIsManifest(Path filePath); boolean fileIsManifest(Path filePath);
/**
* Parses the given file. Will only be called if
* fileIsManifest() previously returned true.
* @param filePath Path to manifest file
* @return Parsed results
* @throws org.sleuthkit.autopsy.experimental.autoingest.ManifestFileParser.ManifestFileParserException
*/
Manifest parse(Path filePath) throws ManifestFileParserException; Manifest parse(Path filePath) throws ManifestFileParserException;
public final static class ManifestFileParserException extends Exception { public final static class ManifestFileParserException extends Exception {

View File

@ -35,6 +35,7 @@ import org.openide.util.actions.Presenter;
import org.openide.windows.WindowManager; import org.openide.windows.WindowManager;
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.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule; import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule;
@ -64,7 +65,7 @@ public final class OpenAction extends CallableSystemAction implements Presenter.
toolbarButton.addActionListener(actionEvent -> performAction()); toolbarButton.addActionListener(actionEvent -> performAction());
pcl = (PropertyChangeEvent evt) -> { pcl = (PropertyChangeEvent evt) -> {
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) { if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
setEnabled(evt.getNewValue() != null); setEnabled(RuntimeProperties.runningWithGUI() && evt.getNewValue() != null);
} }
}; };
Case.addPropertyChangeListener(pcl); Case.addPropertyChangeListener(pcl);

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2013-16 Basis Technology Corp. * Copyright 2011-17 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");
@ -54,7 +54,7 @@ public class GroupSortBy implements Comparator<DrawableGroup> {
/** /**
* sort the groups by some priority metric to be determined and implemented * sort the groups by some priority metric to be determined and implemented
*/ */
public final static GroupSortBy PRIORITY = new GroupSortBy(Bundle.GroupSortBy_priority(), "hashset_hits.png", Comparator.comparing(DrawableGroup::getHashHitDensity).thenComparing(Comparator.comparing(DrawableGroup::getUncategorizedCount))); public final static GroupSortBy PRIORITY = new GroupSortBy(Bundle.GroupSortBy_priority(), "hashset_hits.png", Comparator.comparing(DrawableGroup::getHashHitDensity).thenComparing(Comparator.comparing(DrawableGroup::getUncategorizedCount)).reversed());
@Override @Override
public int compare(DrawableGroup o1, DrawableGroup o2) { public int compare(DrawableGroup o1, DrawableGroup o2) {

View File

@ -5,10 +5,6 @@
<!-- module dependencies --> <!-- module dependencies -->
<conf name="autopsy"/> <conf name="autopsy"/>
<!-- Solr index upgrade tool dependencies -->
<conf name="solr4to5"/>
<conf name="solr5to6"/>
<!-- Solr server dependencies --> <!-- Solr server dependencies -->
<conf name="solr-libs"/> <conf name="solr-libs"/>
<conf name="solr-war"/> <conf name="solr-war"/>
@ -22,19 +18,6 @@
<dependency conf="solr-libs->default" org="org.apache.solr" name="solr-cell" rev="4.9.1"/> <dependency conf="solr-libs->default" org="org.apache.solr" name="solr-cell" rev="4.9.1"/>
<dependency conf="solr-war->default" org="org.apache.solr" name="solr" rev="4.9.1" transitive="false" /> <!-- the war file --> <dependency conf="solr-war->default" org="org.apache.solr" name="solr" rev="4.9.1" transitive="false" /> <!-- the war file -->
<!-- Solr index upgrade -->
<dependency conf="solr4to5->default" org="org.apache.lucene" name="lucene-analyzers-common" rev="5.5.1"/>
<dependency conf="solr4to5->default" org="org.apache.lucene" name="lucene-backward-codecs" rev="5.5.1"/>
<dependency conf="solr4to5->default" org="org.apache.lucene" name="lucene-codecs" rev="5.5.1"/>
<dependency conf="solr4to5->default" org="org.apache.lucene" name="lucene-core" rev="5.5.1"/>
<dependency conf="solr5to6->default" org="org.apache.lucene" name="lucene-analyzers-common" rev="6.2.1"/>
<dependency conf="solr5to6->default" org="org.apache.lucene" name="lucene-backward-codecs" rev="6.2.1"/>
<dependency conf="solr5to6->default" org="org.apache.lucene" name="lucene-codecs" rev="6.2.1"/>
<dependency conf="solr5to6->default" org="org.apache.lucene" name="lucene-core" rev="6.2.1"/>
<!-- Autopsy --> <!-- Autopsy -->
<dependency conf="autopsy->*" org="org.apache.solr" name="solr-solrj" rev="4.9.1"/> <dependency conf="autopsy->*" org="org.apache.solr" name="solr-solrj" rev="4.9.1"/>
<dependency conf="autopsy->*" org="commons-lang" name="commons-lang" rev="2.4"/> <dependency conf="autopsy->*" org="commons-lang" name="commons-lang" rev="2.4"/>

View File

@ -124,9 +124,6 @@ file.reference.slf4j-api-1.7.12.jar=release/modules/ext/slf4j-api-1.7.12.jar
file.reference.solr-solrj-4.9.1-javadoc.jar=release/modules/ext/solr-solrj-4.9.1-javadoc.jar file.reference.solr-solrj-4.9.1-javadoc.jar=release/modules/ext/solr-solrj-4.9.1-javadoc.jar
file.reference.solr-solrj-4.9.1-sources.jar=release/modules/ext/solr-solrj-4.9.1-sources.jar file.reference.solr-solrj-4.9.1-sources.jar=release/modules/ext/solr-solrj-4.9.1-sources.jar
file.reference.solr-solrj-4.9.1.jar=release/modules/ext/solr-solrj-4.9.1.jar file.reference.solr-solrj-4.9.1.jar=release/modules/ext/solr-solrj-4.9.1.jar
file.reference.solr-solrj-6.2.1-javadoc.jar=release/modules/ext/solr-solrj-6.2.1-javadoc.jar
file.reference.solr-solrj-6.2.1-sources.jar=release/modules/ext/solr-solrj-6.2.1-sources.jar
file.reference.solr-solrj-6.2.1.jar=release/modules/ext/solr-solrj-6.2.1.jar
file.reference.spring-aop-3.1.2.RELEASE.jar=release/modules/ext/spring-aop-3.1.2.RELEASE.jar file.reference.spring-aop-3.1.2.RELEASE.jar=release/modules/ext/spring-aop-3.1.2.RELEASE.jar
file.reference.spring-asm-3.1.2.RELEASE.jar=release/modules/ext/spring-asm-3.1.2.RELEASE.jar file.reference.spring-asm-3.1.2.RELEASE.jar=release/modules/ext/spring-asm-3.1.2.RELEASE.jar
file.reference.spring-beans-3.1.2.RELEASE.jar=release/modules/ext/spring-beans-3.1.2.RELEASE.jar file.reference.spring-beans-3.1.2.RELEASE.jar=release/modules/ext/spring-beans-3.1.2.RELEASE.jar

View File

@ -213,7 +213,7 @@ Server.queryNumFileChunks.exception.msg=Error getting number of file chunks,
Server.query.exception.msg=Error running query\: {0} Server.query.exception.msg=Error running query\: {0}
Server.query2.exception.msg=Error running query\: {0} Server.query2.exception.msg=Error running query\: {0}
Server.queryTerms.exception.msg=Error running terms query\: {0} Server.queryTerms.exception.msg=Error running terms query\: {0}
Server.connect.exception.msg=Failed to connect to Solr server\: Server.connect.exception.msg=Failed to connect to Solr server\: {0}
Server.openCore.exception.msg=Keyword search service not yet running Server.openCore.exception.msg=Keyword search service not yet running
Server.openCore.exception.cantOpen.msg=Could not create or open index Server.openCore.exception.cantOpen.msg=Could not create or open index
Server.openCore.exception.noIndexDir.msg=Index directory could not be created or is missing Server.openCore.exception.noIndexDir.msg=Index directory could not be created or is missing
@ -315,8 +315,6 @@ GlobalListsManagementPanel.copyListButton.text=Copy List
GlobalListsManagementPanel.renameListButton.text=Edit List Name GlobalListsManagementPanel.renameListButton.text=Edit List Name
GlobalEditListPanel.editWordButton.text=Edit Keyword GlobalEditListPanel.editWordButton.text=Edit Keyword
SolrSearchService.ServiceName=Solr Keyword Search Service SolrSearchService.ServiceName=Solr Keyword Search Service
SolrSearchService.IndexUpgradeDialog.title=Text Index Upgrade Required In Order To Open Case
SolrSearchService.IndexUpgradeDialog.msg=<html>The text index upgrade can take some time. <br />When completed, you will be able to see existing keyword search results and perform literal keyword searches,<br />but you will not be able to add new text to the index or perform regex searches. You may instead open the case<br /> with your previous version of this application. Do you wish to proceed with the index upgrade?</html>
SolrSearchService.IndexReadOnlyDialog.title=Text Index Is Read-Only SolrSearchService.IndexReadOnlyDialog.title=Text Index Is Read-Only
SolrSearchService.IndexReadOnlyDialog.msg=<html>The text index for this case is read-only. <br />You will be able to see existing keyword search results and perform literal keyword searches,<br />but you will not be able to add new text to the index or perform regex searches. You may instead open the case<br /> with your previous version of this application.</html> SolrSearchService.IndexReadOnlyDialog.msg=<html>The text index for this case is read-only. <br />You will be able to see existing keyword search results and perform exact match and substring match keyword searches,<br />but you will not be able to add new text to the index or perform regex searches. You may instead open the case<br /> with your previous version of this application.</html>

View File

@ -270,7 +270,7 @@ HighlightedMatchesSource.getMarkup.queryFailedMsg=<html><pre><span style\\\\\='b
KeywordSearch.openCore.notification.msg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f KeywordSearch.openCore.notification.msg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f
KeywordSearch.closeCore.notification.msg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u9589\u3058\u308b\u969b\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f KeywordSearch.closeCore.notification.msg=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3092\u9589\u3058\u308b\u969b\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f
KeywordSearchListsManagementPanel.fileExtensionFilterLb2=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30f3\u30b1\u30fc\u30b9\u3059\u308b(txt) KeywordSearchListsManagementPanel.fileExtensionFilterLb2=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u30d5\u30a1\u30a4\u30eb\u3092\u30a8\u30f3\u30b1\u30fc\u30b9\u3059\u308b(txt)
Server.connect.exception.msg=Solr\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\uff1a Server.connect.exception.msg=Solr\u30b5\u30fc\u30d0\u30fc\u3078\u306e\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f\uff1a{0}
Server.openCore.exception.noIndexDir.msg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u307e\u305f\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002 Server.openCore.exception.noIndexDir.msg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30c7\u30a3\u30ec\u30af\u30c8\u30ea\u3092\u4f5c\u6210\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u307e\u305f\u306f\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002
KeywordSearchIngestModule.startUp.noOpenCore.msg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u307e\u305f\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002 KeywordSearchIngestModule.startUp.noOpenCore.msg=\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u304c\u958b\u3051\u307e\u305b\u3093\u3067\u3057\u305f\u3002\u307e\u305f\u306f\u5b58\u5728\u3057\u307e\u305b\u3093\u3002
SolrConnectionCheck.HostnameOrPort=hostname\u3084\u30dd\u30fc\u30c8\u756a\u53f7\u304c\u7121\u52b9\u3067\u3059\u3002 SolrConnectionCheck.HostnameOrPort=hostname\u3084\u30dd\u30fc\u30c8\u756a\u53f7\u304c\u7121\u52b9\u3067\u3059\u3002

View File

@ -19,6 +19,9 @@
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import com.google.common.collect.Iterators; import com.google.common.collect.Iterators;
import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import com.google.common.collect.TreeRangeSet;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -32,6 +35,7 @@ import java.util.stream.Collectors;
import javax.annotation.concurrent.GuardedBy; import javax.annotation.concurrent.GuardedBy;
import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest.METHOD; import org.apache.solr.client.solrj.SolrRequest.METHOD;
import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.client.solrj.response.QueryResponse;
@ -337,7 +341,6 @@ class HighlightedText implements IndexedText {
@Override @Override
public String getText() { public String getText() {
try { try {
loadPageInfo(); //inits once loadPageInfo(); //inits once
SolrQuery q = new SolrQuery(); SolrQuery q = new SolrQuery();
@ -349,15 +352,22 @@ class HighlightedText implements IndexedText {
contentIdStr += "0".equals(chunkID) ? "" : "_" + chunkID; contentIdStr += "0".equals(chunkID) ? "" : "_" + chunkID;
} }
final String filterQuery = Server.Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(contentIdStr); final String filterQuery = Server.Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(contentIdStr);
double indexSchemaVersion = NumberUtils.toDouble(solrServer.getIndexInfo().getSchemaVersion());
//choose field to highlight based on isLiteral and Solr index schema version.
String highlightField = (isLiteral || (indexSchemaVersion < 2.0))
? LuceneQuery.HIGHLIGHT_FIELD
: Server.Schema.CONTENT_STR.toString();
if (isLiteral) { if (isLiteral) {
//if the query is literal try to get solr to do the highlighting
final String highlightQuery = keywords.stream() final String highlightQuery = keywords.stream()
.map(HighlightedText::constructEscapedSolrQuery) .map(HighlightedText::constructEscapedSolrQuery)
.collect(Collectors.joining(" ")); .collect(Collectors.joining(" "));
q.setQuery(highlightQuery); q.setQuery(highlightQuery);
q.addField(Server.Schema.TEXT.toString()); q.addField(highlightField);
q.addFilterQuery(filterQuery); q.addFilterQuery(filterQuery);
q.addHighlightField(LuceneQuery.HIGHLIGHT_FIELD); q.addHighlightField(highlightField);
q.setHighlightFragsize(0); // don't fragment the highlight, works with original highlighter, or needs "single" list builder with FVH q.setHighlightFragsize(0); // don't fragment the highlight, works with original highlighter, or needs "single" list builder with FVH
//tune the highlighter //tune the highlighter
@ -369,8 +379,12 @@ class HighlightedText implements IndexedText {
//docs says makes sense for the original Highlighter only, but not really //docs says makes sense for the original Highlighter only, but not really
q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); //NON-NLS q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); //NON-NLS
} else { } else {
/*
* if the query is not literal just pull back the text. We will
* do the highlighting in autopsy.
*/
q.setQuery(filterQuery); q.setQuery(filterQuery);
q.addField(Server.Schema.CONTENT_STR.toString()); q.addField(highlightField);
} }
QueryResponse response = solrServer.query(q, METHOD.POST); QueryResponse response = solrServer.query(q, METHOD.POST);
@ -383,9 +397,7 @@ class HighlightedText implements IndexedText {
} }
String highlightedContent; String highlightedContent;
Map<String, Map<String, List<String>>> responseHighlight = response.getHighlighting(); Map<String, Map<String, List<String>>> responseHighlight = response.getHighlighting();
String highlightField = isLiteral
? LuceneQuery.HIGHLIGHT_FIELD
: Server.Schema.CONTENT_STR.toString();
if (responseHighlight == null) { if (responseHighlight == null) {
highlightedContent = attemptManualHighlighting(response.getResults(), highlightField, keywords); highlightedContent = attemptManualHighlighting(response.getResults(), highlightField, keywords);
} else { } else {
@ -433,6 +445,7 @@ class HighlightedText implements IndexedText {
return 0; return 0;
} }
return this.numberOfHitsPerPage.get(this.currentPage); return this.numberOfHitsPerPage.get(this.currentPage);
} }
/** /**
@ -445,7 +458,7 @@ class HighlightedText implements IndexedText {
* to a Solr query. We expect there to only ever be * to a Solr query. We expect there to only ever be
* a single document. * a single document.
* *
* @return Either a string with the keyword highlighted or a string * @return Either a string with the keyword highlighted via HTML span tags or a string
* indicating that we did not find a hit in the document. * indicating that we did not find a hit in the document.
*/ */
static String attemptManualHighlighting(SolrDocumentList solrDocumentList, String highlightField, Collection<String> keywords) { static String attemptManualHighlighting(SolrDocumentList solrDocumentList, String highlightField, Collection<String> keywords) {
@ -465,38 +478,41 @@ class HighlightedText implements IndexedText {
// not see highlighted text in the content viewer. // not see highlighted text in the content viewer.
text = StringEscapeUtils.escapeHtml(text); text = StringEscapeUtils.escapeHtml(text);
StringBuilder highlightedText = new StringBuilder(""); TreeRangeSet<Integer> highlights = TreeRangeSet.create();
//do a highlighting pass for each keyword //for each keyword find the locations of hits and record them in the RangeSet
for (String keyword : keywords) { for (String keyword : keywords) {
//we also need to escape the keyword so that it matches the escpared text //we also need to escape the keyword so that it matches the escaped text
final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword); final String escapedKeyword = StringEscapeUtils.escapeHtml(keyword);
int textOffset = 0; int searchOffset = 0;
int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset); int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, searchOffset);
while (hitOffset != -1) { while (hitOffset != -1) {
// Append the portion of text up to (but not including) the hit. // Advance the search offset past the keyword.
highlightedText.append(text.substring(textOffset, hitOffset)); searchOffset = hitOffset + escapedKeyword.length();
// Add in the highlighting around the keyword.
highlightedText.append(HIGHLIGHT_PRE);
highlightedText.append(keyword);
highlightedText.append(HIGHLIGHT_POST);
// Advance the text offset past the keyword. //record the location of the hit, possibly merging it with other hits
textOffset = hitOffset + escapedKeyword.length(); highlights.add(Range.closedOpen(hitOffset, searchOffset));
hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset); //look for next hit
hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, searchOffset);
} }
// Append the remainder of text field
highlightedText.append(text.substring(textOffset, text.length()));
if (highlightedText.length() == 0) {
return NbBundle.getMessage(HighlightedText.class, "HighlightedMatchesSource.getMarkup.noMatchMsg");
}
//reset for next pass
text = highlightedText.toString();
highlightedText = new StringBuilder("");
} }
return text;
StringBuilder highlightedText = new StringBuilder(text);
int totalHighLightLengthInserted = 0;
//for each range to be highlighted...
for (Range<Integer> highlightRange : highlights.asRanges()) {
int hStart = highlightRange.lowerEndpoint();
int hEnd = highlightRange.upperEndpoint();
//insert the pre and post tag, adjusting indices for previously added tags
highlightedText.insert(hStart + totalHighLightLengthInserted, HIGHLIGHT_PRE);
totalHighLightLengthInserted += HIGHLIGHT_PRE.length();
highlightedText.insert(hEnd + totalHighLightLengthInserted, HIGHLIGHT_POST);
totalHighLightLengthInserted += HIGHLIGHT_POST.length();
}
return highlightedText.toString();
} }
/** /**

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 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");
@ -25,6 +25,8 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.logging.Level; import java.util.logging.Level;
import net.htmlparser.jericho.Attributes; import net.htmlparser.jericho.Attributes;
import net.htmlparser.jericho.Config;
import net.htmlparser.jericho.LoggerProvider;
import net.htmlparser.jericho.Renderer; import net.htmlparser.jericho.Renderer;
import net.htmlparser.jericho.Source; import net.htmlparser.jericho.Source;
import net.htmlparser.jericho.StartTag; import net.htmlparser.jericho.StartTag;
@ -50,6 +52,11 @@ class HtmlTextExtractor extends FileTextExtractor {
"text/javascript" //NON-NLS "text/javascript" //NON-NLS
); );
static {
// Disable Jericho HTML Parser log messages.
Config.LoggerProvider = LoggerProvider.DISABLED;
}
@Override @Override
boolean isContentTypeSpecific() { boolean isContentTypeSpecific() {
return true; return true;

View File

@ -27,7 +27,7 @@ import java.util.List;
import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.math.NumberUtils;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.framework.AutopsyService; import org.sleuthkit.autopsy.appservices.AutopsyService;
/** /**
* This class handles the task of finding and identifying KWS index folders. * This class handles the task of finding and identifying KWS index folders.

View File

@ -315,16 +315,16 @@ class Ingester {
* *
* @return The field map of fields that are common to all file classes. * @return The field map of fields that are common to all file classes.
*/ */
private Map<String, String> getCommonFields(AbstractFile af) { private Map<String, String> getCommonFields(AbstractFile file) {
Map<String, String> params = new HashMap<>(); Map<String, String> params = new HashMap<>();
params.put(Server.Schema.ID.toString(), Long.toString(af.getId())); params.put(Server.Schema.ID.toString(), Long.toString(file.getId()));
try { try {
params.put(Server.Schema.IMAGE_ID.toString(), Long.toString(af.getDataSource().getId())); params.put(Server.Schema.IMAGE_ID.toString(), Long.toString(file.getDataSource().getId()));
} catch (TskCoreException ex) { } catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Could not get data source id to properly index the file " + af.getId(), ex); //NON-NLS logger.log(Level.SEVERE, "Could not get data source id to properly index the file " + file.getId(), ex); //NON-NLS
params.put(Server.Schema.IMAGE_ID.toString(), Long.toString(-1)); params.put(Server.Schema.IMAGE_ID.toString(), Long.toString(-1));
} }
params.put(Server.Schema.FILE_NAME.toString(), af.getName()); params.put(Server.Schema.FILE_NAME.toString(), file.getName());
return params; return params;
} }

View File

@ -1,7 +1,7 @@
/* /*
* Autopsy Forensic Browser * Autopsy Forensic Browser
* *
* Copyright 2011-2016 Basis Technology Corp. * Copyright 2011-2017 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");
@ -446,7 +446,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
} }
if (extractor == null) { if (extractor == null) {
logger.log(Level.INFO, "No text extractor found for file id:{0}, name: {1}, detected format: {2}", new Object[]{aFile.getId(), aFile.getName(), detectedFormat}); //NON-NLS // No text extractor found.
return false; return false;
} }
@ -561,7 +561,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
return; return;
} }
if (!extractTextAndIndex(aFile, fileType)) { if (!extractTextAndIndex(aFile, fileType)) {
logger.log(Level.WARNING, "Text extractor not found for file. Extracting strings only. File: ''{0}'' (id:{1}).", new Object[]{aFile.getName(), aFile.getId()}); //NON-NLS // Text extractor not found for file. Extract string only.
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT); putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
} else { } else {
putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED); putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);

View File

@ -187,7 +187,7 @@ public class Server {
private int currentSolrServerPort = 0; private int currentSolrServerPort = 0;
private int currentSolrStopPort = 0; private int currentSolrStopPort = 0;
private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT); private static final boolean DEBUG = false;//(Version.getBuildType() == Version.Type.DEVELOPMENT);
private static final String SOLR = "solr"; private static final String SOLR = "solr";
private static final String CORE_PROPERTIES = "core.properties"; private static final String CORE_PROPERTIES = "core.properties";
public enum CORE_EVT_STATES { public enum CORE_EVT_STATES {
@ -636,7 +636,7 @@ public class Server {
* Creates/opens a Solr core (index) for a case. * Creates/opens a Solr core (index) for a case.
* *
* @param theCase The case for which the core is to be created/opened. * @param theCase The case for which the core is to be created/opened.
* @param index The text index that the Solr core should be using. * @param index The text index that the Solr core should be using.
* *
* @throws KeywordSearchModuleException If an error occurs while * @throws KeywordSearchModuleException If an error occurs while
* creating/opening the core. * creating/opening the core.
@ -713,7 +713,6 @@ public class Server {
/** /**
* ** end single-case specific methods *** * ** end single-case specific methods ***
*/ */
/** /**
* Deletes the keyword search core for a case. * Deletes the keyword search core for a case.
* *
@ -721,46 +720,41 @@ public class Server {
*/ */
@NbBundle.Messages({ @NbBundle.Messages({
"# {0} - core name", "Server.deleteCore.exception.msg=Failed to delete Solr core {0}",}) "# {0} - core name", "Server.deleteCore.exception.msg=Failed to delete Solr core {0}",})
void deleteCore(String coreName) throws KeywordSearchServiceException { void deleteCore(String coreName, Case.CaseType caseType) throws KeywordSearchServiceException {
/*
* Send a core unload request to the Solr server, with the parameters
* that request deleting the index and the instance directory
* (deleteInstanceDir removes everything related to the core, the index
* directory, the configuration files, etc.) set to true.
* NOTE: this method doesn't delete the actual Solr index directory. That is
* done as part of deleting case output directory.
*/
// check whether the core we are deleting is the currently open core
currentCoreLock.readLock().lock();
try { try {
if (null != currentCore) { HttpSolrServer solrServer;
if (currentCore.getName().equals(coreName)) { if (caseType == CaseType.SINGLE_USER_CASE) {
// close current core first Integer localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
closeCore(); solrServer = new HttpSolrServer("http://localhost:" + localSolrServerPort + "/solr"); //NON-NLS
} } else {
String host = UserPreferences.getIndexingServerHost();
String port = UserPreferences.getIndexingServerPort();
solrServer = new HttpSolrServer("http://" + host + ":" + port + "/solr"); //NON-NLS
} }
} catch (KeywordSearchModuleException ex) {
throw new KeywordSearchServiceException(NbBundle.getMessage(Server.class, "Server.close.exception.msg"), ex);
} finally {
currentCoreLock.readLock().unlock();
}
try {
HttpSolrServer solrServer = new HttpSolrServer("http://" + UserPreferences.getIndexingServerHost() + ":" + UserPreferences.getIndexingServerPort() + "/solr"); //NON-NLS
connectToSolrServer(solrServer); connectToSolrServer(solrServer);
org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName, true, true, solrServer); CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer);
} catch (SolrServerException | IOException ex) { if (null != response.getCoreStatus(coreName).get("instanceDir")) { //NON-NLS
/*
* Send a core unload request to the Solr server, with the
* parameter set that request deleting the index and the
* instance directory (deleteInstanceDir = true). Note that this
* removes everything related to the core on the server (the
* index directory, the configuration files, etc.), but does not
* delete the actual Solr text index because it is currently
* stored in the case directory.
*/
org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName, true, true, solrServer);
}
} catch (SolrServerException | HttpSolrServer.RemoteSolrException | IOException ex) {
throw new KeywordSearchServiceException(Bundle.Server_deleteCore_exception_msg(coreName), ex); throw new KeywordSearchServiceException(Bundle.Server_deleteCore_exception_msg(coreName), ex);
} }
} }
/** /**
* Creates/opens a Solr core (index) for a case. * Creates/opens a Solr core (index) for a case.
* *
* @param theCase The case for which the core is to be created/opened. * @param theCase The case for which the core is to be created/opened.
* @param index The text index that the Solr core should be using. * @param index The text index that the Solr core should be using.
* *
* @return An object representing the created/opened core. * @return An object representing the created/opened core.
* *
@ -780,7 +774,7 @@ public class Server {
connectToSolrServer(currentSolrServer); connectToSolrServer(currentSolrServer);
} catch (SolrServerException | IOException ex) { } catch (SolrServerException | IOException ex) {
throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg"), ex); throw new KeywordSearchModuleException(NbBundle.getMessage(Server.class, "Server.connect.exception.msg", ex.getLocalizedMessage()), ex);
} }
try { try {
@ -891,8 +885,8 @@ public class Server {
} }
/** /**
* Execute query that gets only number of all Solr file chunks (not * Execute query that gets only number of all Solr file chunks (not logical
* logical files) indexed without actually returning the content. * files) indexed without actually returning the content.
* *
* @return int representing number of indexed chunks * @return int representing number of indexed chunks
* *
@ -916,8 +910,8 @@ public class Server {
} }
/** /**
* Execute query that gets only number of all Solr documents indexed * Execute query that gets only number of all Solr documents indexed (files
* (files and chunks) without actually returning the documents * and chunks) without actually returning the documents
* *
* @return int representing number of indexed files (files and chunks) * @return int representing number of indexed files (files and chunks)
* *
@ -970,11 +964,10 @@ public class Server {
/** /**
* Execute query that gets number of indexed file chunks for a file * Execute query that gets number of indexed file chunks for a file
* *
* @param fileID file id of the original file broken into chunks and * @param fileID file id of the original file broken into chunks and indexed
* indexed
* *
* @return int representing number of indexed file chunks, 0 if there is * @return int representing number of indexed file chunks, 0 if there is no
* no chunks * chunks
* *
* @throws KeywordSearchModuleException * @throws KeywordSearchModuleException
* @throws NoOpenCoreException * @throws NoOpenCoreException
@ -1206,8 +1199,7 @@ public class Server {
} }
/** /**
* Determines whether or not the index files folder for a Solr core * Determines whether or not the index files folder for a Solr core exists.
* exists.
* *
* @param coreName the name of the core. * @param coreName the name of the core.
* *
@ -1385,8 +1377,8 @@ public class Server {
* Execute query that gets only number of all Solr files (not chunks) * Execute query that gets only number of all Solr files (not chunks)
* indexed without actually returning the files * indexed without actually returning the files
* *
* @return int representing number of indexed files (entire files, * @return int representing number of indexed files (entire files, not
* not chunks) * chunks)
* *
* @throws SolrServerException * @throws SolrServerException
*/ */
@ -1447,11 +1439,11 @@ public class Server {
/** /**
* Execute query that gets number of indexed file chunks for a file * Execute query that gets number of indexed file chunks for a file
* *
* @param contentID file id of the original file broken into chunks * @param contentID file id of the original file broken into chunks and
* and indexed * indexed
* *
* @return int representing number of indexed file chunks, 0 if there * @return int representing number of indexed file chunks, 0 if there is
* is no chunks * no chunks
* *
* @throws SolrServerException * @throws SolrServerException
*/ */

View File

@ -18,6 +18,7 @@
*/ */
package org.sleuthkit.autopsy.keywordsearch; package org.sleuthkit.autopsy.keywordsearch;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.InetAddress; import java.net.InetAddress;
@ -37,9 +38,10 @@ import org.openide.util.lookup.ServiceProviders;
import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.CaseMetadata;
import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.FileUtil;
import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.framework.AutopsyService; import org.sleuthkit.autopsy.appservices.AutopsyService;
import org.sleuthkit.autopsy.framework.ProgressIndicator; import org.sleuthkit.autopsy.progress.ProgressIndicator;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException;
import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact;
@ -50,7 +52,8 @@ import org.sleuthkit.datamodel.TskCoreException;
* text indexing and search. * text indexing and search.
*/ */
@ServiceProviders(value = { @ServiceProviders(value = {
@ServiceProvider(service = KeywordSearchService.class), @ServiceProvider(service = KeywordSearchService.class)
,
@ServiceProvider(service = AutopsyService.class)} @ServiceProvider(service = AutopsyService.class)}
) )
public class SolrSearchService implements KeywordSearchService, AutopsyService { public class SolrSearchService implements KeywordSearchService, AutopsyService {
@ -138,16 +141,17 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
} }
} }
@NbBundle.Messages({"# {0} - case directory",
"SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from caseDirectory: {0}",
"# {0} - case directory",
"SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case"
})
/** /**
* Deletes Solr core for a case. * Deletes Solr core for a case.
* *
* @param metadata The CaseMetadata which will have its core deleted. * @param metadata The CaseMetadata which will have its core deleted.
*/ */
@NbBundle.Messages({"# {0} - case directory",
"SolrSearchService.exceptionMessage.noIndexMetadata=Unable to create IndexMetaData from caseDirectory: {0}",
"# {0} - case directory",
"SolrSearchService.exceptionMessage.noCurrentSolrCore=IndexMetadata did not contain a current Solr core so could not delete the case",
"SolrSearchService.exceptionMessage.failedToDeleteIndexFiles=Failed to delete text index files at {0}"
})
@Override @Override
public void deleteTextIndex(CaseMetadata metadata) throws KeywordSearchServiceException { public void deleteTextIndex(CaseMetadata metadata) throws KeywordSearchServiceException {
String caseDirectory = metadata.getCaseDirectory(); String caseDirectory = metadata.getCaseDirectory();
@ -163,13 +167,23 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
String currentSolr = IndexFinder.getCurrentSolrVersion(); String currentSolr = IndexFinder.getCurrentSolrVersion();
for (Index index : indexMetadata.getIndexes()) { for (Index index : indexMetadata.getIndexes()) {
if (index.getSolrVersion().equals(currentSolr) && index.getSchemaVersion().equals(currentSchema)) { if (index.getSolrVersion().equals(currentSolr) && index.getSchemaVersion().equals(currentSchema)) {
KeywordSearch.getServer().deleteCore(index.getIndexName()); /*
return; //only one core exists for each combination of solr and schema version * Unload/delete the core on the server and then delete the text
* index files.
*/
KeywordSearch.getServer().deleteCore(index.getIndexName(), metadata.getCaseType());
if (!FileUtil.deleteDir(new File(index.getIndexPath()).getParentFile())) {
throw new KeywordSearchServiceException(Bundle.SolrSearchService_exceptionMessage_failedToDeleteIndexFiles(index.getIndexPath()));
}
} }
return; //only one core exists for each combination of solr and schema version
} }
//this code this code will only execute if an index for the current core was not found //this code this code will only execute if an index for the current core was not found
logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class, "SolrSearchService.exceptionMessage.noCurrentSolrCore")); logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class,
throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, "SolrSearchService.exceptionMessage.noCurrentSolrCore")); "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class,
"SolrSearchService.exceptionMessage.noCurrentSolrCore"));
} }
@Override @Override
@ -200,6 +214,10 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
"SolrSearch.openCore.msg=Opening text index", "SolrSearch.openCore.msg=Opening text index",
"SolrSearch.complete.msg=Text index successfully opened"}) "SolrSearch.complete.msg=Text index successfully opened"})
public void openCaseResources(CaseContext context) throws AutopsyServiceException { public void openCaseResources(CaseContext context) throws AutopsyServiceException {
if (context.cancelRequested()) {
return;
}
ProgressIndicator progress = context.getProgressIndicator(); ProgressIndicator progress = context.getProgressIndicator();
int totalNumProgressUnits = 7; int totalNumProgressUnits = 7;
int progressUnitsCompleted = 0; int progressUnitsCompleted = 0;

View File

@ -174,13 +174,10 @@ class StringsTextExtractor extends FileTextExtractor {
private final byte[] oneCharBuf = new byte[1]; private final byte[] oneCharBuf = new byte[1];
/** /**
* Construct new string stream from FsContent Do not attempt to fill * Construct new string stream from FsContent. Do not attempt to fill
* entire read buffer if that would break a string * entire read buffer if that would break a string
* *
* @param content to extract strings from * @param content Content object from which to extract strings.
* @param outputCharset target charset to encode into bytes and index
* as, e.g. UTF-8
*
*/ */
private EnglishOnlyStream(AbstractFile content) { private EnglishOnlyStream(AbstractFile content) {
this.content = content; this.content = content;
@ -378,8 +375,10 @@ class StringsTextExtractor extends FileTextExtractor {
private final AbstractFile content; private final AbstractFile content;
private final byte[] oneCharBuf = new byte[1]; private final byte[] oneCharBuf = new byte[1];
private final StringExtract stringExtractor; private final StringExtract stringExtractor;
/** true if there is nothing to do because neither extractUTF8 nor /**
* extractUTF16 was true in constructor */ * true if there is nothing to do because neither extractUTF8 nor
* extractUTF16 was true in constructor
*/
private final boolean nothingToDo; private final boolean nothingToDo;
private final byte[] fileReadBuff = new byte[FILE_BUF_SIZE]; private final byte[] fileReadBuff = new byte[FILE_BUF_SIZE];
private long fileReadOffset = 0L; private long fileReadOffset = 0L;

View File

@ -57,7 +57,6 @@ class TikaTextExtractor extends FileTextExtractor {
@Override @Override
public void logWarning(final String msg, Exception ex) { public void logWarning(final String msg, Exception ex) {
KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex); KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex);
logger.log(Level.WARNING, msg, ex); //NON-NLS }
} }
@Override @Override

View File

@ -1,3 +1,26 @@
---------------- VERSION 4.4.0 --------------
Improvements:
- Keyword search supports regular expressions that include spaces.
- Improvements to keyword search highlighting and standard regular expressions.
- User can edit keyword lists.
- Simultaneous acquisition of a sparse VHD from a USB device during analysis.
- Support for ingest profiles that combine file ingest filters with ingest
module settings.
- Artifact attributes can be marked to indicate discovery by multiple tools.
- Import/export of interesting files set membership rules.
- High DPI display support added.
- Support for application service plug-in modules (Java only).
- Progress dialogs for case create/open/close/delete operations that support
cancellation of create/open operations and cancellation of the opening of case
resources by individual application services.
- Coordination service now used for all multi-user cases, not just auto
ingest cases; e.g., any open multi-user case cannot be deleted by another user.
- Updated Recent Activity ingest module to use RegRipper 2.8 plugins.
- Updated version of Tika used for extracting text.
- Updated version of POI used for extracting embedded MS Office documents.
- Ability to customize HTML report logo.
- Assorted small enhancements and bug fixes.
---------------- VERSION 4.3.0 -------------- ---------------- VERSION 4.3.0 --------------
Improvements: Improvements:
- Support for slack space on files (as separate virtual files) to enable keyword searching and other analysis. - Support for slack space on files (as separate virtual files) to enable keyword searching and other analysis.

View File

@ -17,9 +17,11 @@
</target> </target>
<!-- use manifestclasspath (http://ant.apache.org/manual/Tasks/manifestclasspath.html) to put all the jar files that we need for junit/regression test <!-- use manifestclasspath (http://ant.apache.org/manual/Tasks/manifestclasspath.html) to put all the jar files that we need for junit/regression test
to a single jar file: allJarsInUse.jar. Then we put this new jar to classpath for testing program to avoid command line Java classpath too long problem. --> to a single jar file: allJarsInUse.jar. Then we put this new jar to classpath for testing program to avoid command line Java classpath too long problem.
Note: Started from ant 1.10, maxParentLevels are enforced. If you get error from manifestclasspath complaines 'No suitable relative path from ...' then it's time to
increase your maxParentLevels -->
<target name="manifest-classpath"> <target name="manifest-classpath">
<manifestclasspath property="tem.classpath" jarfile="allJarsInUse.jar"> <manifestclasspath property="tem.classpath" jarfile="allJarsInUse.jar" maxParentLevels="5">
<classpath refid="test.${regression}.run.cp"/> <classpath refid="test.${regression}.run.cp"/>
</manifestclasspath> </manifestclasspath>
<jar destfile="allJarsInUse.jar" basedir="build/classes"> <jar destfile="allJarsInUse.jar" basedir="build/classes">

View File

@ -59,11 +59,9 @@ public class AutopsyTestCases {
private long start; private long start;
/** /**
* This method is used to escape file/directory path. Example: * Escapes the slashes in a file or directory path.
* \\NetworkLocation\foo\bar get escaped to \\\\NetworkLocation\foo\bar so
* that it can be used as intended.
* *
* @param path * @param path The path to be escaped.
* *
* @return escaped path the the file/directory location. * @return escaped path the the file/directory location.
*/ */
@ -78,7 +76,7 @@ public class AutopsyTestCases {
} }
} }
public AutopsyTestCases () { public AutopsyTestCases() {
start = 0; start = 0;
} }
@ -107,7 +105,10 @@ public class AutopsyTestCases {
public void testStartAddImageFileDataSource() { public void testStartAddImageFileDataSource() {
logger.info("Starting Add Image process"); logger.info("Starting Add Image process");
WizardOperator wo = new WizardOperator("Add Data"); WizardOperator wo = new WizardOperator("Add Data Source");
while(!wo.btNext().isEnabled()){
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
}
//select the toggle button for Disk Image or VM File it will be the first button created and proceed to next panel //select the toggle button for Disk Image or VM File it will be the first button created and proceed to next panel
JToggleButtonOperator jtbo = new JToggleButtonOperator(wo, 0); JToggleButtonOperator jtbo = new JToggleButtonOperator(wo, 0);
jtbo.clickMouse(); jtbo.clickMouse();
@ -123,7 +124,10 @@ public class AutopsyTestCases {
public void testStartAddLogicalFilesDataSource() { public void testStartAddLogicalFilesDataSource() {
logger.info("Starting Add Logical Files process"); logger.info("Starting Add Logical Files process");
WizardOperator wo = new WizardOperator("Add Data"); WizardOperator wo = new WizardOperator("Add Data Source");
while(!wo.btNext().isEnabled()){
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
}
//select the toggle button for Logical Files it will be the third button created and proceed to next panel //select the toggle button for Logical Files it will be the third button created and proceed to next panel
JToggleButtonOperator jtbo = new JToggleButtonOperator(wo, 2); JToggleButtonOperator jtbo = new JToggleButtonOperator(wo, 2);
jtbo.clickMouse(); jtbo.clickMouse();
@ -139,7 +143,7 @@ public class AutopsyTestCases {
} }
public void testAddSourceWizard1() { public void testAddSourceWizard1() {
WizardOperator wo = new WizardOperator("Add Data"); WizardOperator wo = new WizardOperator("Add Data Source");
while (!wo.btFinish().isEnabled()) { while (!wo.btFinish().isEnabled()) {
new Timeout("pausing", 1000).sleep(); // give it a second (or five) to process new Timeout("pausing", 1000).sleep(); // give it a second (or five) to process
} }
@ -155,7 +159,10 @@ public class AutopsyTestCases {
new Timeout("pausing", 10000).sleep(); new Timeout("pausing", 10000).sleep();
logger.info("Looking for hash lookup module in ingest job settings panel"); logger.info("Looking for hash lookup module in ingest job settings panel");
WizardOperator wo = new WizardOperator("Add Data"); WizardOperator wo = new WizardOperator("Add Data Source");
while(!wo.btNext().isEnabled()){
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
}
JTableOperator jto = new JTableOperator(wo, 0); JTableOperator jto = new JTableOperator(wo, 0);
int row = jto.findCellRow("Hash Lookup", 2, 0); int row = jto.findCellRow("Hash Lookup", 2, 0);
jto.clickOnCell(row, 1); jto.clickOnCell(row, 1);
@ -201,7 +208,10 @@ public class AutopsyTestCases {
public void testConfigureIngest2() { public void testConfigureIngest2() {
logger.info("Looking for keyword search module in ingest job settings panel"); logger.info("Looking for keyword search module in ingest job settings panel");
WizardOperator wo = new WizardOperator("Add Data"); WizardOperator wo = new WizardOperator("Add Data Source");
while(!wo.btNext().isEnabled()){
new Timeout("pausing", 1000).sleep(); // give it a second till the Add Data Source dialog enabled
}
JTableOperator jto = new JTableOperator(wo, 0); JTableOperator jto = new JTableOperator(wo, 0);
int row = jto.findCellRow("Keyword Search", 2, 0); int row = jto.findCellRow("Keyword Search", 2, 0);
jto.clickOnCell(row, 1); jto.clickOnCell(row, 1);
@ -234,7 +244,7 @@ public class AutopsyTestCases {
} }
JButtonOperator jbo2 = new JButtonOperator(jdo, "OK", 0); JButtonOperator jbo2 = new JButtonOperator(jdo, "OK", 0);
jbo2.pushNoBlock(); jbo2.pushNoBlock();
WizardOperator wo = new WizardOperator("Add Data"); WizardOperator wo = new WizardOperator("Add Data Source");
new Timeout("pausing", 10000).sleep(); // let things catch up new Timeout("pausing", 10000).sleep(); // let things catch up
wo.btNext().clickMouse(); wo.btNext().clickMouse();
} }

View File

@ -76,6 +76,8 @@
<unzip src="${nbdist.dir}/${app.name}.zip" dest="${zip-tmp}"/> <unzip src="${nbdist.dir}/${app.name}.zip" dest="${zip-tmp}"/>
<!-- step (3) do your copying stuff here, check the ant doc for copy, move, etc file --> <!-- step (3) do your copying stuff here, check the ant doc for copy, move, etc file -->
<copy file="${nbplatform.active.dir}/platform/modules/ext/junit-4.10.jar"
tofile="${zip-tmp}/${app.name}/platform/modules/ext/junit-4.10.jar"/>
<copy file="${basedir}/README.txt" tofile="${zip-tmp}/${app.name}/README.txt"/> <copy file="${basedir}/README.txt" tofile="${zip-tmp}/${app.name}/README.txt"/>
<copy file="${basedir}/LICENSE-2.0.txt" tofile="${zip-tmp}/${app.name}/LICENSE-2.0.txt"/> <copy file="${basedir}/LICENSE-2.0.txt" tofile="${zip-tmp}/${app.name}/LICENSE-2.0.txt"/>
<copy file="${basedir}/NEWS.txt" tofile="${zip-tmp}/${app.name}/NEWS.txt"/> <copy file="${basedir}/NEWS.txt" tofile="${zip-tmp}/${app.name}/NEWS.txt"/>

18
developers/README.txt Executable file
View File

@ -0,0 +1,18 @@
Common NetBeans IDE settings for the Autopsy project are stored here.
All contributors are kindly asked to use these settings.
1. To make Java code formatting (pretty-printing) settings, select Tools,
Options, Editor tab, Formatting tab. Push the Import... button to pop up the
Select Options to Import dialog. Push the Browse... button to pop up a file
chooser. Select ~\autopsy\developers\netbeans_ide_formatting_settings.zip.
NetBeans IDE will require a restart for the settings to take effect. Formatting
can be done by selecting Source, Format (Alt + Shift + F).
2. To make Java code hygiene hints (lint) settings, copy the entire contents of
~\autopsy\developers\netbeans_ide_java_hint_settings to the hint/default
subdirectory of your user settings directory for the IDE. For Windows, this is
~\AppData\Roaming\NetBeans\8.2\config\Preferences\org\netbeans\modules\java\hints
\default. Restart the IDE.

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

View File

@ -0,0 +1 @@
enabled=true

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