mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-13 08:26:15 +00:00
Merge remote-tracking branch 'upstream/develop' into 2210-cleanup
# Conflicts: # Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java
This commit is contained in:
commit
6f3f993073
@ -15,7 +15,7 @@
|
||||
|
||||
<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="org.apache.zookeeper" name="zookeeper" rev="3.4.6"/>
|
||||
|
||||
|
@ -12,7 +12,7 @@ file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbi
|
||||
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.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.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
|
||||
|
@ -243,6 +243,7 @@
|
||||
<package>net.sf.sevenzipjbinding.simple</package>
|
||||
<package>net.sf.sevenzipjbinding.simple.impl</package>
|
||||
<package>org.sleuthkit.autopsy.actions</package>
|
||||
<package>org.sleuthkit.autopsy.appservices</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule.events</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule.services</package>
|
||||
@ -254,17 +255,18 @@
|
||||
<package>org.sleuthkit.autopsy.corecomponents</package>
|
||||
<package>org.sleuthkit.autopsy.coreutils</package>
|
||||
<package>org.sleuthkit.autopsy.datamodel</package>
|
||||
<package>org.sleuthkit.autopsy.datasourceprocessors</package>
|
||||
<package>org.sleuthkit.autopsy.directorytree</package>
|
||||
<package>org.sleuthkit.autopsy.events</package>
|
||||
<package>org.sleuthkit.autopsy.externalresults</package>
|
||||
<package>org.sleuthkit.autopsy.filesearch</package>
|
||||
<package>org.sleuthkit.autopsy.framework</package>
|
||||
<package>org.sleuthkit.autopsy.ingest</package>
|
||||
<package>org.sleuthkit.autopsy.keywordsearchservice</package>
|
||||
<package>org.sleuthkit.autopsy.menuactions</package>
|
||||
<package>org.sleuthkit.autopsy.modules.filetypeid</package>
|
||||
<package>org.sleuthkit.autopsy.modules.hashdatabase</package>
|
||||
<package>org.sleuthkit.autopsy.modules.vmextractor</package>
|
||||
<package>org.sleuthkit.autopsy.progress</package>
|
||||
<package>org.sleuthkit.autopsy.report</package>
|
||||
<package>org.sleuthkit.datamodel</package>
|
||||
</public-packages>
|
||||
@ -325,8 +327,8 @@
|
||||
<binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/tika-core-1.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/tika-core-1.5.jar</binary-origin>
|
||||
<runtime-relative-path>ext/tika-core-1.14.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/tika-core-1.14.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/metadata-extractor-2.8.1.jar</runtime-relative-path>
|
||||
|
@ -174,10 +174,6 @@ public class DeleteFileBlackboardArtifactTagAction extends AbstractAction implem
|
||||
for(BlackboardArtifactTag artifactTag : existingTagsList) {
|
||||
if(tagDisplayName.equals(artifactTag.getName().getDisplayName())) {
|
||||
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) -> {
|
||||
deleteTag(tagName, artifactTag, artifact.getArtifactID());
|
||||
});
|
||||
|
@ -159,8 +159,6 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
|
||||
// a tag with the associated tag name.
|
||||
if (null != tagNamesMap && !tagNamesMap.isEmpty()) {
|
||||
try {
|
||||
/*List<BlackboardArtifactTag> existingTagsList =
|
||||
Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagsByArtifact(artifact);*/
|
||||
List<ContentTag> existingTagsList =
|
||||
Case.getCurrentCase().getServices().getTagsManager()
|
||||
.getContentTagsByContent(file);
|
||||
@ -172,10 +170,6 @@ public class DeleteFileContentTagAction extends AbstractAction implements Presen
|
||||
for(ContentTag contentTag : existingTagsList) {
|
||||
if(tagDisplayName.equals(contentTag.getName().getDisplayName())) {
|
||||
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) -> {
|
||||
deleteTag(tagName, contentTag, file.getId());
|
||||
});
|
||||
|
@ -16,9 +16,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.framework;
|
||||
package org.sleuthkit.autopsy.appservices;
|
||||
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.progress.ProgressIndicator;
|
||||
|
||||
/**
|
||||
* An interface for services that report status and may manage case and
|
@ -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.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.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\
|
||||
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\
|
||||
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
|
||||
@ -136,12 +136,6 @@ IntervalErrorReport.NewIssues=new issue(s)
|
||||
IntervalErrorReport.TotalIssues=total issue(s)
|
||||
IntervalErrorReport.ErrorText=Database Connection Error
|
||||
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
|
||||
GeneralFilter.rawImageDesc.text=Raw Images (*.img, *.dd, *.001, *.aa, *.raw, *.bin)
|
||||
GeneralFilter.encaseImageDesc.text=Encase Images (*.e01)
|
||||
|
@ -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\
|
||||
{0}
|
||||
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.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
|
||||
@ -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.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
|
||||
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
|
||||
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)
|
||||
|
File diff suppressed because it is too large
Load Diff
49
Core/src/org/sleuthkit/autopsy/casemodule/CaseActionCancelledException.java
Executable file
49
Core/src/org/sleuthkit/autopsy/casemodule/CaseActionCancelledException.java
Executable 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);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,15 +19,30 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
/**
|
||||
* Exception thrown when case action (such as open, close, create) resulted in
|
||||
* an error
|
||||
* Exception thrown when a case action (e.g., create, open, close, delete)
|
||||
* experiences an error condition.
|
||||
*/
|
||||
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) {
|
||||
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) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
@ -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);
|
||||
JOptionPane.showMessageDialog(
|
||||
null,
|
||||
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getMessage()),
|
||||
Bundle.Case_deleteCaseFailureMessageBox_message(ex.getLocalizedMessage()),
|
||||
Bundle.Case_deleteCaseFailureMessageBox_title(),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
@ -99,6 +99,7 @@ final class CaseDeleteAction extends CallableSystemAction {
|
||||
* of the Delete button that invokes this action.
|
||||
*/
|
||||
CasePropertiesAction.closeCasePropertiesWindow();
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,10 +19,6 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
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 org.openide.util.NbBundle.Messages;
|
||||
|
||||
@ -32,44 +28,40 @@ import org.openide.util.NbBundle.Messages;
|
||||
*/
|
||||
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() {
|
||||
initComponents();
|
||||
customizeComponents();
|
||||
}
|
||||
|
||||
@Messages({"CaseInformationPanel.caseDetails.header=Case Details",
|
||||
"CaseInformationPanel.ingestJobInfo.header=Ingest History",
|
||||
"CaseInformationPanel.loadMetadataFail.message=Failed to load case metadata.",
|
||||
"CaseInformationPanel.loadMetadataFail.title=Metadata load failure",})
|
||||
@Messages({
|
||||
"CaseInformationPanel.caseDetails.header=Case Details",
|
||||
"CaseInformationPanel.ingestJobInfo.header=Ingest History"
|
||||
})
|
||||
private void customizeComponents() {
|
||||
try {
|
||||
Case currentCase = Case.getCurrentCase();
|
||||
String crDate = currentCase.getCreatedDate();
|
||||
String caseDir = currentCase.getCaseDirectory();
|
||||
|
||||
// put the image paths information into hashmap
|
||||
Map<Long, String> imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase());
|
||||
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);
|
||||
}
|
||||
CasePropertiesPanel propertiesPanel = new CasePropertiesPanel(Case.getCurrentCase());
|
||||
propertiesPanel.setSize(propertiesPanel.getPreferredSize());
|
||||
this.tabbedPane.addTab(Bundle.CaseInformationPanel_caseDetails_header(), propertiesPanel);
|
||||
this.tabbedPane.addTab(Bundle.CaseInformationPanel_ingestJobInfo_header(), new IngestJobInfoPanel());
|
||||
this.tabbedPane.addChangeListener((ChangeEvent e) -> {
|
||||
tabbedPane.getSelectedComponent().setSize(tabbedPane.getSelectedComponent().getPreferredSize());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an action listener to the Close button of the panel.
|
||||
*
|
||||
* @param action
|
||||
*/
|
||||
void addCloseButtonAction(ActionListener action) {
|
||||
this.closeButton.addActionListener(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -127,7 +119,7 @@ class CaseInformationPanel extends javax.swing.JPanel {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
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
|
||||
|
||||
|
||||
|
@ -54,7 +54,9 @@ public final class CaseMetadata {
|
||||
private static final String FILE_EXTENSION = ".aut";
|
||||
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 final static String ROOT_ELEMENT_NAME = "AutopsyCase"; //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 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 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
|
||||
|
||||
//fields from schema version 3
|
||||
/*
|
||||
* Fields from schema version 3
|
||||
*/
|
||||
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_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 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 Case.CaseType caseType;
|
||||
@ -92,8 +100,8 @@ public final class CaseMetadata {
|
||||
private String caseNumber;
|
||||
private String examiner;
|
||||
private String caseDatabaseName;
|
||||
private String caseDatabasePath;
|
||||
private String textIndexName;
|
||||
private String caseDatabasePath; // Legacy
|
||||
private String textIndexName; // Legacy
|
||||
private String createdDate;
|
||||
private String createdByVersion;
|
||||
|
||||
@ -107,8 +115,9 @@ public final class CaseMetadata {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object that provides access to the case metadata stored in
|
||||
* a new case metadata file that is created using the supplied metadata.
|
||||
* Constructs a CaseMetadata object for a new case. The metadata is not
|
||||
* persisted to the case metadata file until writeFile or a setX method is
|
||||
* called.
|
||||
*
|
||||
* @param caseDirectory The case directory.
|
||||
* @param caseType The type of case.
|
||||
@ -117,29 +126,24 @@ public final class CaseMetadata {
|
||||
* user.
|
||||
* @param caseNumber The case number.
|
||||
* @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);
|
||||
this.caseType = caseType;
|
||||
this.caseName = caseName;
|
||||
this.caseDisplayName = caseDisplayName;
|
||||
this.caseNumber = caseNumber;
|
||||
this.examiner = examiner;
|
||||
this.caseDatabaseName = caseDatabase;
|
||||
caseDatabaseName = "";
|
||||
caseDatabasePath = "";
|
||||
textIndexName = "";
|
||||
createdByVersion = Version.getVersion();
|
||||
createdDate = CaseMetadata.DATE_FORMAT.format(new Date());
|
||||
writeToFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an object that provides access to the case metadata stored in
|
||||
* an existing case metadata file.
|
||||
* Constructs a CaseMetadata object for an existing case. The metadata is
|
||||
* read from an existing 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.
|
||||
*/
|
||||
@ -193,22 +197,23 @@ public final class CaseMetadata {
|
||||
* @return The case display name.
|
||||
*/
|
||||
public String getCaseDisplayName() {
|
||||
return this.caseDisplayName;
|
||||
return caseDisplayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the case display name. This does not change the name of the case
|
||||
* directory, the case database, or the text index name.
|
||||
* Sets the case display 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 {
|
||||
String oldCaseName = caseName;
|
||||
this.caseDisplayName = caseName;
|
||||
void setCaseDisplayName(String caseDisplayName) throws CaseMetadataException {
|
||||
String oldCaseDisplayName = this.caseDisplayName;
|
||||
this.caseDisplayName = caseDisplayName;
|
||||
try {
|
||||
writeToFile();
|
||||
} catch (CaseMetadataException ex) {
|
||||
this.caseDisplayName = oldCaseName;
|
||||
this.caseDisplayName = oldCaseDisplayName;
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
@ -234,32 +239,35 @@ public final class CaseMetadata {
|
||||
/**
|
||||
* Gets the name of the case database.
|
||||
*
|
||||
* @return The case database name.
|
||||
* @return The case database name, may be empty.
|
||||
*/
|
||||
public String getCaseDatabaseName() {
|
||||
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 {
|
||||
String oldIndexName = caseTextIndexName;
|
||||
this.textIndexName = caseTextIndexName;
|
||||
void setCaseDatabaseName(String caseDatabaseName) throws CaseMetadataException {
|
||||
String oldCaseDatabaseName = this.caseDatabaseName;
|
||||
this.caseDatabaseName = caseDatabaseName;
|
||||
try {
|
||||
writeToFile();
|
||||
} catch (CaseMetadataException ex) {
|
||||
this.textIndexName = oldIndexName;
|
||||
this.caseDatabaseName = oldCaseDatabaseName;
|
||||
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() {
|
||||
return textIndexName;
|
||||
@ -268,7 +276,7 @@ public final class CaseMetadata {
|
||||
/**
|
||||
* 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() {
|
||||
return createdDate;
|
||||
@ -278,7 +286,9 @@ public final class CaseMetadata {
|
||||
* Sets the date the case was created. Used for preserving the case creation
|
||||
* 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 {
|
||||
String oldCreatedDate = createdDate;
|
||||
@ -304,13 +314,15 @@ public final class CaseMetadata {
|
||||
* Sets the Autopsy version that created the case. Used for preserving this
|
||||
* 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 {
|
||||
String oldCreatedByVersion = this.createdByVersion;
|
||||
this.createdByVersion = buildVersion;
|
||||
try {
|
||||
this.writeToFile();
|
||||
writeToFile();
|
||||
} catch (CaseMetadataException ex) {
|
||||
this.createdByVersion = oldCreatedByVersion;
|
||||
throw ex;
|
||||
@ -381,8 +393,8 @@ public final class CaseMetadata {
|
||||
createChildElement(doc, caseElement, CASE_NUMBER_ELEMENT_NAME, caseNumber);
|
||||
createChildElement(doc, caseElement, EXAMINER_ELEMENT_NAME, examiner);
|
||||
createChildElement(doc, caseElement, CASE_TYPE_ELEMENT_NAME, caseType.toString());
|
||||
createChildElement(doc, caseElement, CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME, caseDatabasePath);
|
||||
createChildElement(doc, caseElement, CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME, caseDatabaseName);
|
||||
createChildElement(doc, caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, caseDatabasePath);
|
||||
createChildElement(doc, caseElement, CASE_DB_NAME_RELATIVE_ELEMENT_NAME, caseDatabaseName);
|
||||
createChildElement(doc, caseElement, TEXT_INDEX_ELEMENT, textIndexName);
|
||||
}
|
||||
|
||||
@ -451,15 +463,19 @@ public final class CaseMetadata {
|
||||
if (null == this.caseType) {
|
||||
throw new CaseMetadataException("Case metadata file corrupted");
|
||||
}
|
||||
if (schemaVersion.equals(SCHEMA_VERSION_ONE)) {
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
|
||||
} else if (schemaVersion.equals(SCHEMA_VERSION_TWO)) {
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_ABSOLUTE_PATH_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
|
||||
} else {
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_RELATIVE_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_ELEMENT, false);
|
||||
switch (schemaVersion) {
|
||||
case SCHEMA_VERSION_ONE:
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DATABASE_NAME_ELEMENT_NAME, true);
|
||||
this.textIndexName = getElementTextContent(caseElement, TEXT_INDEX_NAME_ELEMENT, true);
|
||||
break;
|
||||
case SCHEMA_VERSION_TWO:
|
||||
this.caseDatabaseName = getElementTextContent(caseElement, CASE_DB_ABSOLUTE_PATH_ELEMENT_NAME, true);
|
||||
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 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
|
||||
* 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.
|
||||
*
|
||||
* @throws UnsupportedOperationException If called for a multi-user case.
|
||||
* @deprecated
|
||||
* @deprecated Do not use.
|
||||
*/
|
||||
@Deprecated
|
||||
public String getCaseDatabasePath() throws UnsupportedOperationException {
|
||||
|
@ -115,26 +115,19 @@ public final class CaseOpenAction extends CallableSystemAction implements Action
|
||||
protected void done() {
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException ex) {
|
||||
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));
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
if (ex instanceof InterruptedException || (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException))) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
|
||||
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();
|
||||
} catch (ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", path), ex); //NON-NLS
|
||||
} finally {
|
||||
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();
|
||||
}
|
||||
|
@ -22,7 +22,6 @@ import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.SwingUtilities;
|
||||
@ -43,34 +42,29 @@ final class CasePropertiesAction extends CallableSystemAction {
|
||||
CasePropertiesAction() {
|
||||
putValue(Action.NAME, NbBundle.getMessage(CasePropertiesAction.class, "CTL_CasePropertiesAction"));
|
||||
this.setEnabled(false);
|
||||
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), new PropertyChangeListener() {
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent evt) {
|
||||
setEnabled(null != evt.getNewValue());
|
||||
}
|
||||
Case.addEventSubscriber(Case.Events.CURRENT_CASE.toString(), (PropertyChangeEvent evt) -> {
|
||||
setEnabled(null != evt.getNewValue());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
if (null == casePropertiesDialog) {
|
||||
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
|
||||
casePropertiesDialog = new JDialog(WindowManager.getDefault().getMainWindow(), title, false);
|
||||
CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
|
||||
caseInformationPanel.addCloseButtonAction((ActionEvent e) -> {
|
||||
casePropertiesDialog.setVisible(false);
|
||||
});
|
||||
casePropertiesDialog.add(caseInformationPanel);
|
||||
casePropertiesDialog.setResizable(true);
|
||||
casePropertiesDialog.pack();
|
||||
String title = NbBundle.getMessage(this.getClass(), "CasePropertiesAction.window.title");
|
||||
casePropertiesDialog = new JDialog(WindowManager.getDefault().getMainWindow(), title, false);
|
||||
CaseInformationPanel caseInformationPanel = new CaseInformationPanel();
|
||||
caseInformationPanel.addCloseButtonAction((ActionEvent e) -> {
|
||||
casePropertiesDialog.setVisible(false);
|
||||
});
|
||||
casePropertiesDialog.add(caseInformationPanel);
|
||||
casePropertiesDialog.setResizable(true);
|
||||
casePropertiesDialog.pack();
|
||||
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
double w = casePropertiesDialog.getSize().getWidth();
|
||||
double h = casePropertiesDialog.getSize().getHeight();
|
||||
casePropertiesDialog.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
|
||||
casePropertiesDialog.setVisible(true);
|
||||
}
|
||||
Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
|
||||
double w = casePropertiesDialog.getSize().getWidth();
|
||||
double h = casePropertiesDialog.getSize().getHeight();
|
||||
casePropertiesDialog.setLocation((int) ((screenDimension.getWidth() - w) / 2), (int) ((screenDimension.getHeight() - h) / 2));
|
||||
casePropertiesDialog.setVisible(true);
|
||||
casePropertiesDialog.setVisible(true);
|
||||
casePropertiesDialog.toFront();
|
||||
});
|
||||
@ -87,6 +81,9 @@ final class CasePropertiesAction extends CallableSystemAction {
|
||||
}
|
||||
|
||||
static void closeCasePropertiesWindow() {
|
||||
casePropertiesDialog.setVisible(false);
|
||||
if (null != casePropertiesDialog) {
|
||||
casePropertiesDialog.setVisible(false);
|
||||
casePropertiesDialog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,63 +16,57 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
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.actions.CallableSystemAction;
|
||||
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
|
||||
* and change the display name of the case.
|
||||
* A panel that allows the user to view various properties of a case and change
|
||||
* the display name of the case.
|
||||
*/
|
||||
class CasePropertiesPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private Case current = null;
|
||||
private static JPanel caller; // panel for error
|
||||
private static final Logger LOGGER = Logger.getLogger(CasePropertiesPanel.class.getName());
|
||||
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();
|
||||
caseNameTextField.setText(currentCase.getDisplayName());
|
||||
String caseNumber = currentCase.getNumber();
|
||||
theCase = aCase;
|
||||
caseNameTextField.setText(theCase.getDisplayName());
|
||||
String caseNumber = theCase.getNumber();
|
||||
if (!caseNumber.isEmpty()) {
|
||||
caseNumberField.setText(caseNumber);
|
||||
} else {
|
||||
caseNumberField.setText("N/A");
|
||||
}
|
||||
String examiner = currentCase.getExaminer();
|
||||
String examiner = theCase.getExaminer();
|
||||
if (!examiner.isEmpty()) {
|
||||
examinerField.setText(examiner);
|
||||
} else {
|
||||
examinerField.setText("N/A");
|
||||
}
|
||||
crDateField.setText(crDate);
|
||||
caseDirField.setText(caseDir);
|
||||
current = currentCase;
|
||||
|
||||
CaseMetadata caseMetadata = currentCase.getCaseMetadata();
|
||||
if (caseMetadata.getCaseType() == Case.CaseType.SINGLE_USER_CASE) {
|
||||
dbNameField.setText(Paths.get(caseMetadata.getCaseDirectory(), caseMetadata.getCaseDatabaseName()).toString());
|
||||
crDateField.setText(theCase.getCreatedDate());
|
||||
caseDirField.setText(theCase.getCaseDirectory());
|
||||
if (Case.CaseType.SINGLE_USER_CASE == theCase.getCaseType()) {
|
||||
dbNameField.setText(Paths.get(theCase.getCaseDirectory(), theCase.getMetadata().getCaseDatabaseName()).toString());
|
||||
} else {
|
||||
dbNameField.setText(caseMetadata.getCaseDatabaseName());
|
||||
dbNameField.setText(theCase.getMetadata().getCaseDatabaseName());
|
||||
}
|
||||
Case.CaseType caseType = caseMetadata.getCaseType();
|
||||
Case.CaseType caseType = theCase.getCaseType();
|
||||
caseTypeField.setText(caseType.getLocalizedDisplayName());
|
||||
if (caseType == Case.CaseType.SINGLE_USER_CASE) {
|
||||
deleteCaseButton.setEnabled(true);
|
||||
} else {
|
||||
deleteCaseButton.setEnabled(false);
|
||||
}
|
||||
deleteCaseButton.setEnabled(Case.CaseType.SINGLE_USER_CASE == caseType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -259,59 +253,35 @@ class CasePropertiesPanel extends javax.swing.JPanel {
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
/**
|
||||
* Updates the case name.
|
||||
* Updates the case display name.
|
||||
*
|
||||
* @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
|
||||
String oldCaseName = Case.getCurrentCase().getDisplayName();
|
||||
String newCaseName = caseNameTextField.getText();
|
||||
// check if the old and new case name is not equal
|
||||
if (!oldCaseName.equals(newCaseName)) {
|
||||
String newCaseDisplayName = caseNameTextField.getText();
|
||||
if (newCaseDisplayName.equals(theCase.getDisplayName())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// check if the case name is empty
|
||||
if (newCaseName.trim().isEmpty()) {
|
||||
JOptionPane.showMessageDialog(caller,
|
||||
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);
|
||||
if (newCaseDisplayName.trim().isEmpty()) {
|
||||
MessageNotifyUtil.Message.error(Bundle.CasePropertiesPanel_errorDialog_emptyCaseNameMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
Object res = DialogDisplayer.getDefault().notify(d);
|
||||
if (res != null && res == DialogDescriptor.YES_OPTION) {
|
||||
// if user select "Yes"
|
||||
String oldPath = current.getCaseMetadata().getFilePath().toString();
|
||||
try {
|
||||
current.updateCaseName(oldCaseName, oldPath, newCaseName, oldPath);
|
||||
} catch (CaseActionException ex) {
|
||||
Logger.getLogger(CasePropertiesPanel.class.getName()).log(Level.WARNING, "Error: problem updating case name.", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!Case.isValidName(newCaseDisplayName)) {
|
||||
MessageNotifyUtil.Message.error(Bundle.CasePropertiesPanel_errorDialog_invalidCaseNameMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
theCase.updateDisplayName(newCaseDisplayName);
|
||||
} 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
|
||||
|
||||
|
@ -33,7 +33,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
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
|
||||
|
@ -31,7 +31,7 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgress
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.DriveUtils;
|
||||
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
|
||||
|
@ -29,7 +29,7 @@ import org.openide.util.lookup.ServiceProviders;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorProgressMonitor;
|
||||
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
|
||||
|
@ -94,15 +94,17 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
|
||||
addImageAction.actionPerformed(null);
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
|
||||
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
|
||||
logger.log(Level.SEVERE, String.format("Error creating case %s", wizardDescriptor.getProperty("caseName")), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
(ex instanceof ExecutionException ? ex.getCause().getMessage() : ex.getMessage()),
|
||||
NbBundle.getMessage(this.getClass(), "CaseCreateAction.msgDlg.cantCreateCase.msg"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
StartupWindowProvider.getInstance().close();
|
||||
StartupWindowProvider.getInstance().open();
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
} finally {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
|
@ -38,29 +38,21 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
/**
|
||||
* The "New Case" wizard panel with a component on it. This class represents
|
||||
* data of wizard step. It defers creation and initialization of UI component of
|
||||
* wizard panel into getComponent() method.
|
||||
* The first panel of the New Case wizard.
|
||||
*/
|
||||
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 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
|
||||
* 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.
|
||||
* Get the visual component for the panel.
|
||||
*
|
||||
* @return component the UI component of this wizard panel
|
||||
* @return The UI component of this wizard panel
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
* for the wizard dialog.
|
||||
* Gets the help object for this panel. When the panel is active, this is
|
||||
* used as the help for the wizard dialog.
|
||||
*
|
||||
* @return HelpCtx.DEFAULT_HELP the help for this panel
|
||||
* @return The help for this panel.
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelp() {
|
||||
// Show no Help button for this panel:
|
||||
/*
|
||||
* Currently, no help is provided for this panel.
|
||||
*/
|
||||
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"
|
||||
* button will be enabled.
|
||||
*
|
||||
* @return boolean true if all the fields are correctly filled, false
|
||||
* otherwise
|
||||
* @return boolean True if all the fields are correctly filled, false
|
||||
* otherwise.
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
// If it is always OK to press Next or Finish, then:
|
||||
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
|
||||
public final void addChangeListener(ChangeListener l) {
|
||||
public final void addChangeListener(ChangeListener listener) {
|
||||
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
|
||||
public final void removeChangeListener(ChangeListener l) {
|
||||
public final void removeChangeListener(ChangeListener listener) {
|
||||
synchronized (listeners) {
|
||||
listeners.remove(l);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is auto-generated. It seems that this method is used to
|
||||
* listen to any change in this wizard panel.
|
||||
* Notifies any registerd change listeners of a change in the panel.
|
||||
*/
|
||||
protected final void fireChangeEvent() {
|
||||
Iterator<ChangeListener> it;
|
||||
@ -153,12 +137,8 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
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
|
||||
* buttons. This method can be called multiple times on one instance of
|
||||
* WizardDescriptor.Panel.
|
||||
@ -322,4 +302,5 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
|
||||
/**
|
||||
* The "New Case" wizard panel with a component on it. This class represents
|
||||
* data of wizard step. It defers creation and initialization of UI component of
|
||||
* wizard panel into getComponent() method.
|
||||
*
|
||||
* @author jantonius
|
||||
* The second panel of the New Case wizard.
|
||||
*/
|
||||
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 Boolean isFinish = true;
|
||||
private String caseName;
|
||||
private String caseDir;
|
||||
private String createdDirectory;
|
||||
private CaseType caseType;
|
||||
private final Set<ChangeListener> listeners = new HashSet<>(1);
|
||||
|
||||
/**
|
||||
* Get the visual component for the panel. In this template, the component
|
||||
* 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.
|
||||
* Get the visual component for the panel.
|
||||
*
|
||||
* @return component the UI component of this wizard panel
|
||||
* @return component The UI component of this wizard panel.
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
* for the wizard dialog.
|
||||
* Gets the help object for this panel. When the panel is active, this is
|
||||
* used as the help for the wizard dialog.
|
||||
*
|
||||
* @return HelpCtx.DEFAULT_HELP the help for this panel
|
||||
* @return The help for this panel.
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelp() {
|
||||
// Show no Help button for this panel:
|
||||
/*
|
||||
* Currently, no help is provided for this panel.
|
||||
*/
|
||||
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
|
||||
public boolean isValid() {
|
||||
// If it is always OK to press Next or Finish, then:
|
||||
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.
|
||||
return true;
|
||||
}
|
||||
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
|
||||
public final void addChangeListener(ChangeListener l) {
|
||||
public final void addChangeListener(ChangeListener listener) {
|
||||
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
|
||||
public final void removeChangeListener(ChangeListener l) {
|
||||
public final void removeChangeListener(ChangeListener listener) {
|
||||
synchronized (listeners) {
|
||||
listeners.remove(l);
|
||||
listeners.remove(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is auto-generated. It seems that this method is used to
|
||||
* listen to any change in this wizard panel.
|
||||
* Notifies any registerd change listeners of a change in the panel.
|
||||
*/
|
||||
protected final void fireChangeEvent() {
|
||||
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
|
||||
* or already-modified settings, if the user used the previous and/or next
|
||||
@ -152,10 +124,6 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -100,9 +100,9 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
if (casePaths.length < 1) {
|
||||
return;
|
||||
}
|
||||
final String casePath = casePaths[imagesTable.getSelectedRow()];
|
||||
final String caseMetadataFilePath = casePaths[imagesTable.getSelectedRow()];
|
||||
final String caseName = caseNames[imagesTable.getSelectedRow()];
|
||||
if (!casePath.isEmpty()) {
|
||||
if (!caseMetadataFilePath.isEmpty()) {
|
||||
try {
|
||||
StartupWindowProvider.getInstance().close();
|
||||
CueBannerPanel.closeOpenRecentCasesWindow();
|
||||
@ -113,25 +113,27 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
/*
|
||||
* 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(),
|
||||
NbBundle.getMessage(this.getClass(), "RecentItems.openRecentCase.msgDlg.text", caseName),
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"),
|
||||
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();
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case.openAsCurrentCase(casePath);
|
||||
Case.openAsCurrentCase(caseMetadataFilePath);
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", casePath), ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(), // Should be user-friendly
|
||||
NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
if (!(ex instanceof CaseActionCancelledException)) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(OpenRecentCasePanel.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
StartupWindowProvider.getInstance().open();
|
||||
});
|
||||
}
|
||||
|
@ -407,9 +407,11 @@ final class RecentCases extends CallableSystemAction implements Presenter.Menu {
|
||||
String[] casePaths = new String[LENGTH];
|
||||
String currentCasePath = null;
|
||||
try {
|
||||
currentCasePath = Case.getCurrentCase().getCaseMetadata().getFilePath().toString();
|
||||
currentCasePath = Case.getCurrentCase().getMetadata().getFilePath().toString();
|
||||
} catch (IllegalStateException ex) {
|
||||
// in case there is no current case.
|
||||
/*
|
||||
* There may be no current case.
|
||||
*/
|
||||
}
|
||||
|
||||
Iterator<RecentCase> mostRecentFirst = recentCases.descendingIterator();
|
||||
|
@ -64,14 +64,17 @@ class RecentItems implements ActionListener {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case.openAsCurrentCase(caseMetaDataFilePath);
|
||||
StartupWindowProvider.getInstance().close();
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
if (!(ex instanceof CaseActionCancelledException)) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetaDataFilePath), ex); //NON-NLS
|
||||
JOptionPane.showMessageDialog(
|
||||
WindowManager.getDefault().getMainWindow(),
|
||||
ex.getMessage(),
|
||||
NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), //NON-NLS
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
StartupWindowProvider.getInstance().open();
|
||||
});
|
||||
}
|
||||
|
@ -204,8 +204,8 @@ public class SingleUserCaseConverter {
|
||||
icd.getNewCaseName(),
|
||||
icd.getNewCaseName(),
|
||||
oldCaseMetadata.getCaseNumber(),
|
||||
oldCaseMetadata.getExaminer(),
|
||||
dbName);
|
||||
oldCaseMetadata.getExaminer());
|
||||
newCaseMetadata.setCaseDatabaseName(dbName);
|
||||
// Set created date. This calls writefile, no need to call it again
|
||||
newCaseMetadata.setCreatedDate(oldCaseMetadata.getCreatedDate());
|
||||
newCaseMetadata.setCreatedByVersion(oldCaseMetadata.getCreatedByVersion());
|
||||
|
@ -26,9 +26,12 @@ import java.awt.Graphics;
|
||||
import java.awt.dnd.DnDConstants;
|
||||
import java.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.beans.FeatureDescriptor;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -36,6 +39,8 @@ import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.prefs.Preferences;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.TreeSet;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.ListSelectionModel;
|
||||
import javax.swing.SwingUtilities;
|
||||
@ -44,6 +49,8 @@ import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.event.TableColumnModelEvent;
|
||||
import javax.swing.event.TableColumnModelListener;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
|
||||
import javax.swing.table.TableColumnModel;
|
||||
import org.netbeans.swing.etable.ETableColumn;
|
||||
import org.netbeans.swing.outline.DefaultOutlineCellRenderer;
|
||||
import org.netbeans.swing.outline.DefaultOutlineModel;
|
||||
@ -96,6 +103,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
// the column started and where it ended up.
|
||||
private int startColumnIndex = -1;
|
||||
private int endColumnIndex = -1;
|
||||
private OutlineView ov;
|
||||
|
||||
/*
|
||||
* Convience reference to internal Outline.
|
||||
@ -125,8 +133,8 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
initComponents();
|
||||
|
||||
outlineView.setAllowedDragActions(DnDConstants.ACTION_NONE);
|
||||
outline = outlineView.getOutline();
|
||||
|
||||
outline = outlineView.getOutline();
|
||||
outline.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
|
||||
outline.setRootVisible(false); // don't show the root node
|
||||
outline.setDragEnabled(false);
|
||||
@ -334,7 +342,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
@Override
|
||||
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
|
||||
public void setNode(Node selectedNode) {
|
||||
|
||||
/*
|
||||
* The quick filter must be reset because when determining column width,
|
||||
* 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
|
||||
String[] propStrings = new String[props.size() * 2];
|
||||
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
|
||||
if (i == 0) {
|
||||
props.get(i).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("TreeColumnTTV", Boolean.TRUE); // Identifies special property representing first (tree) 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 + 1] = props.get(i).getDisplayName();
|
||||
propStrings[2 * i] = prop.getName();
|
||||
propStrings[2 * i + 1] = prop.getDisplayName();
|
||||
}
|
||||
|
||||
outlineView.setPropertyColumns(propStrings);
|
||||
@ -474,25 +482,44 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
// Store the current order of the columns into settings
|
||||
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++) {
|
||||
ETableColumn etc = (ETableColumn) outline.getColumnModel().getColumn(i);
|
||||
ETableColumn etc = (ETableColumn) columnModel.getColumn(i);
|
||||
String columnName = ov.getOutline().getColumnName(i);
|
||||
if (etc.isSorted()) {
|
||||
preferences.put(getColumnSortOrderKey(tfn, etc.getIdentifier().toString()), String.valueOf(etc.isAscending()));
|
||||
preferences.put(getColumnSortRankKey(tfn, etc.getIdentifier().toString()), 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()));
|
||||
preferences.put(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.isAscending()));
|
||||
preferences.put(getColumnSortRankKey(tfn.getColumnOrderKey(), columnName), String.valueOf(etc.getSortRank()));
|
||||
} else {
|
||||
preferences.remove(getColumnSortOrderKey(tfn, etc.getIdentifier().toString()));
|
||||
preferences.remove(getColumnSortRankKey(tfn, etc.getIdentifier().toString()));
|
||||
preferences.remove(getColumnSortOrderKey(tfn.getColumnOrderKey(), columnName));
|
||||
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() {
|
||||
if (currentRoot == null || propertiesMap.isEmpty()) {
|
||||
return;
|
||||
@ -502,23 +529,29 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
TableFilterNode tfn = (TableFilterNode) currentRoot;
|
||||
|
||||
Map<Integer, Boolean> orderMap = new TreeMap<>();
|
||||
Map<Integer, Integer> indexMap = new TreeMap<>();
|
||||
if (currentRoot instanceof TableFilterNode) {
|
||||
final String columnOrderKey = ((TableFilterNode) currentRoot).getColumnOrderKey();
|
||||
|
||||
propertiesMap.entrySet().forEach((entry) -> {
|
||||
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.
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
|
||||
orderMap.put(sortRank, sortOrder);
|
||||
indexMap.put(sortRank, outline.getColumn(entry.getValue().getName()).getModelIndex());
|
||||
});
|
||||
//organize property sorting information, sorted by rank
|
||||
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;
|
||||
|
||||
final Preferences preferences = NbPreferences.forModule(DataResultViewerTable.class);
|
||||
|
||||
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)) {
|
||||
propertiesMap.put(value, prop);
|
||||
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
|
||||
* store the column position into a preference file.
|
||||
*
|
||||
* @param propName Property of the column
|
||||
* @param node The current node to use as a base for the property key.
|
||||
* @param prop Property of the column
|
||||
* @param type The type of the current node
|
||||
*
|
||||
* @return A generated key for the preference file
|
||||
*/
|
||||
private String getColumnPositionKey(TableFilterNode node, String propName) {
|
||||
return getColumnKeyBase(node, propName) + ".column"; //NON-NLS
|
||||
private String getColumnPositionKey(String type, String propName) {
|
||||
return getColumnKeyBase(type, propName) + ".column";
|
||||
}
|
||||
|
||||
private String getColumnSortOrderKey(TableFilterNode node, String propName) {
|
||||
return getColumnKeyBase(node, propName) + ".sortOrder";//NON-NLS
|
||||
private String getColumnSortOrderKey(String type, String propName) {
|
||||
return getColumnKeyBase(type, propName) + ".sortOrder";
|
||||
}
|
||||
|
||||
private String getColumnSortRankKey(TableFilterNode node, String propName) {
|
||||
return getColumnKeyBase(node, propName) + ".sortRank";//NON-NLS
|
||||
private String getColumnSortRankKey(String type, String propName) {
|
||||
return getColumnKeyBase(type, propName) + ".sortRank";
|
||||
}
|
||||
|
||||
private static String getColumnKeyBase(TableFilterNode node, String propName) {
|
||||
return stripNonAlphanumeric(node.getColumnOrderKey()) + "." + stripNonAlphanumeric(propName);
|
||||
private static String getColumnKeyBase(String type, String propName) {
|
||||
return stripNonAlphanumeric(type) + "." + stripNonAlphanumeric(propName);
|
||||
}
|
||||
|
||||
private static String stripNonAlphanumeric(String str) {
|
||||
return str.replaceAll("[^a-zA-Z0-9_]", "");//NON-NLS
|
||||
return str.replaceAll("[^a-zA-Z0-9_]", "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 - 2016 Basis Technology Corp.
|
||||
* Copyright 2011 - 2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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(InterestingHits.InterestingItemTypeNode aThis);
|
||||
|
||||
/**
|
||||
* Visitor with an implementable default behavior for all types. Override
|
||||
* specific visit types to not use the default behavior.
|
||||
@ -238,6 +240,11 @@ public interface DisplayableItemNodeVisitor<T> {
|
||||
return defaultVisit(ftByMimeTypeEmptyNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(InterestingHits.InterestingItemTypeNode interestingItemTypeNode) {
|
||||
return defaultVisit(interestingItemTypeNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T visit(DeletedContentNode dcn) {
|
||||
return defaultVisit(dcn);
|
||||
|
@ -453,7 +453,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
* @return query.toString - portion of SQL query which will follow a
|
||||
* WHERE clause.
|
||||
*/
|
||||
private String createQuery(String mime_type) {
|
||||
private String createQuery(String mimeType) {
|
||||
StringBuilder query = new StringBuilder();
|
||||
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
|
||||
@ -466,7 +466,7 @@ public final class FileTypesByMimeType extends Observable implements AutopsyVisi
|
||||
if (UserPreferences.hideKnownFilesInViewsTree()) {
|
||||
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();
|
||||
}
|
||||
|
||||
|
@ -379,9 +379,10 @@ public class HashsetHits implements AutopsyVisitableItem {
|
||||
|
||||
hashsetResults.getArtifactIds(hashsetName).forEach((id) -> {
|
||||
try {
|
||||
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
|
||||
|
||||
artifactHits.put(id, art);
|
||||
if (!artifactHits.containsKey(id)) {
|
||||
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
|
||||
artifactHits.put(id, art);
|
||||
}
|
||||
list.add(id);
|
||||
} catch (TskException ex) {
|
||||
logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -66,7 +66,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
private class InterestingResults extends Observable {
|
||||
|
||||
// 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() {
|
||||
List<String> setNames;
|
||||
@ -77,9 +77,9 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
return setNames;
|
||||
}
|
||||
|
||||
public Set<Long> getArtifactIds(String setName) {
|
||||
public Set<Long> getArtifactIds(String setName, String typeName) {
|
||||
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
|
||||
long artifactId = resultSet.getLong("artifact_id"); //NON-NLS
|
||||
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) {
|
||||
@ -280,7 +282,7 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
private final String setName;
|
||||
|
||||
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;
|
||||
super.setName(setName);
|
||||
updateDisplayName();
|
||||
@ -289,12 +291,14 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
}
|
||||
|
||||
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
|
||||
public boolean isLeafTypeNode() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@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 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();
|
||||
this.setName = setName;
|
||||
this.typeName = typeName;
|
||||
interestingResults.addObserver(this);
|
||||
}
|
||||
|
||||
@ -349,14 +443,15 @@ public class InterestingHits implements AutopsyVisitableItem {
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
|
||||
if (skCase == null) {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
interestingResults.getArtifactIds(setName).forEach((id) -> {
|
||||
interestingResults.getArtifactIds(setName, typeName).forEach((id) -> {
|
||||
try {
|
||||
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
|
||||
|
||||
artifactHits.put(id, art);
|
||||
if (!artifactHits.containsKey(id)) {
|
||||
BlackboardArtifact art = skCase.getBlackboardArtifact(id);
|
||||
artifactHits.put(id, art);
|
||||
}
|
||||
list.add(id);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "TSK Exception occurred", ex); //NON-NLS
|
||||
|
@ -707,14 +707,17 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
if ((instances.size() == 1) && (instances.get(0).equals(DEFAULT_INSTANCE_NAME))) {
|
||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, DEFAULT_INSTANCE_NAME) ) {
|
||||
RegExpInstanceKey key = new RegExpInstanceKey(id);
|
||||
nodesMap.put(key, createNode(key));
|
||||
if (!nodesMap.containsKey(key)) {
|
||||
nodesMap.put(key, createNode(key));
|
||||
}
|
||||
list.add(key);
|
||||
|
||||
}
|
||||
} else {
|
||||
for (String instance : instances) {
|
||||
RegExpInstanceKey key = new RegExpInstanceKey(instance);
|
||||
nodesMap.put(key, createNode(key));
|
||||
if (!nodesMap.containsKey(key)) {
|
||||
nodesMap.put(key, createNode(key));
|
||||
}
|
||||
list.add(key);
|
||||
}
|
||||
|
||||
@ -897,11 +900,12 @@ public class KeywordHits implements AutopsyVisitableItem {
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<Long> list) {
|
||||
list.addAll(keywordResults.getArtifactIds(setName, keyword, instance));
|
||||
for (Long id : keywordResults.getArtifactIds(setName, keyword, instance) ) {
|
||||
if (!nodesMap.containsKey(id)) {
|
||||
nodesMap.put(id, createBlackboardArtifactNode(id));
|
||||
list.add(id);
|
||||
}
|
||||
list.add(id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.framework;
|
||||
package org.sleuthkit.autopsy.datasourceprocessors;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
@ -28,26 +28,27 @@ import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
|
||||
/**
|
||||
* A Raw data source processor that implements the DataSourceProcessor service
|
||||
* provider interface to allow integration with the add data source wizard.
|
||||
* It also provides a run method overload to allow it to be used independently
|
||||
* of the wizard.
|
||||
* provider interface to allow integration with the add data source wizard. It
|
||||
* also provides a run method overload to allow it to be used independently of
|
||||
* the wizard.
|
||||
*/
|
||||
@ServiceProvider(service = DataSourceProcessor.class)
|
||||
public class RawDSProcessor implements DataSourceProcessor {
|
||||
|
||||
private final RawDSInputPanel configPanel;
|
||||
private AddRawImageTask addImageTask;
|
||||
|
||||
/*
|
||||
* Constructs a Raw data source processor that implements the
|
||||
* DataSourceProcessor service provider interface to allow integration
|
||||
* with the add data source wizard. It also provides a run method
|
||||
* overload to allow it to be used independently of the wizard.
|
||||
* DataSourceProcessor service provider interface to allow integration with
|
||||
* the add data source wizard. It also provides a run method overload to
|
||||
* allow it to be used independently of the wizard.
|
||||
*/
|
||||
public RawDSProcessor() {
|
||||
configPanel = RawDSInputPanel.createInstance(RawDSProcessor.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* 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
|
||||
* type selection UI component (e.g., a combo box).
|
||||
@ -68,7 +69,7 @@ public class RawDSProcessor implements DataSourceProcessor {
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
* separate thread and the given settings instead of those provided by the
|
||||
* Adds a "raw" data source to the case database using a background task in
|
||||
* a separate thread and the given settings instead of those provided by the
|
||||
* selection and configuration panel. Returns as soon as the background task
|
||||
* is started and uses the callback object to signal task completion and
|
||||
* return results.
|
||||
*
|
||||
* @param deviceId An ASCII-printable identifier for the
|
||||
* device associated with the data source
|
||||
* that is intended to be unique across
|
||||
* multiple cases (e.g., a UUID).
|
||||
* @param rawDSInputFilePath Path to a Raw data source file.
|
||||
* @param isHandsetFile Indicates whether the XML file is for a
|
||||
* handset or a SIM.
|
||||
* @param progressMonitor Progress monitor for reporting progress
|
||||
* during processing.
|
||||
* @param deviceId An ASCII-printable identifier for the device
|
||||
* associated with the data source that is
|
||||
* intended to be unique across multiple cases
|
||||
* (e.g., a UUID).
|
||||
* @param imageFilePath Path to the image file.
|
||||
* @param timeZone The time zone to use when processing dates
|
||||
* and times for the image, obtained from
|
||||
* java.util.TimeZone.getID.
|
||||
* @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) {
|
||||
addImageTask = new AddRawImageTask(deviceId, imageFilePath, timeZone, chunkSize, progressMonitor, callback);
|
||||
new Thread(addImageTask).start();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
@ -71,8 +71,9 @@ import org.sleuthkit.datamodel.TskException;
|
||||
import org.sleuthkit.datamodel.VirtualDirectory;
|
||||
|
||||
/**
|
||||
* This class wraps nodes as they are passed to the DataResult viewers. It
|
||||
* defines the actions that the node should have.
|
||||
* 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.
|
||||
*/
|
||||
public class DataResultFilterNode extends FilterNode {
|
||||
|
||||
@ -111,22 +112,33 @@ public class DataResultFilterNode extends FilterNode {
|
||||
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 em ExplorerManager for component that is creating the node
|
||||
* @param node The node to wrap.
|
||||
* @param em The ExplorerManager for the component that is creating the
|
||||
* node.
|
||||
*/
|
||||
public DataResultFilterNode(Node node, ExplorerManager em) {
|
||||
super(node, new DataResultFilterChildren(node, 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 em ExplorerManager for component that is creating the node
|
||||
* @param node The node to wrap.
|
||||
* @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));
|
||||
this.sourceEm = em;
|
||||
}
|
||||
@ -201,9 +213,9 @@ public class DataResultFilterNode extends FilterNode {
|
||||
* 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 filterSlack;
|
||||
@ -211,7 +223,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
|
||||
private DataResultFilterChildren(Node arg, ExplorerManager sourceEm) {
|
||||
super(arg);
|
||||
switch (SelectionContext.getSelectionContext(arg)) {
|
||||
case DATA_SOURCES:
|
||||
@ -230,7 +242,7 @@ public class DataResultFilterNode extends FilterNode {
|
||||
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);
|
||||
this.filterKnown = filterKnown;
|
||||
this.filterSlack = filterSlack;
|
||||
@ -326,9 +338,9 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actionsList.add(AddContentTagAction.getInstance());
|
||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
|
||||
final Collection<AbstractFile> selectedFilesList =
|
||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||
if(selectedFilesList.size() == 1) {
|
||||
final Collection<AbstractFile> selectedFilesList
|
||||
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(AbstractFile.class));
|
||||
if (selectedFilesList.size() == 1) {
|
||||
actionsList.add(DeleteFileContentTagAction.getInstance());
|
||||
}
|
||||
} else {
|
||||
@ -338,13 +350,13 @@ public class DataResultFilterNode extends FilterNode {
|
||||
actionsList.add(AddBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
|
||||
final Collection<BlackboardArtifact> selectedArtifactsList =
|
||||
new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||
if(selectedArtifactsList.size() == 1) {
|
||||
final Collection<BlackboardArtifact> selectedArtifactsList
|
||||
= new HashSet<>(Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class));
|
||||
if (selectedArtifactsList.size() == 1) {
|
||||
actionsList.add(DeleteFileBlackboardArtifactTagAction.getInstance());
|
||||
}
|
||||
|
||||
if(n != null) {
|
||||
if (n != null) {
|
||||
actionsList.addAll(ContextMenuExtensionPoint.getActions());
|
||||
}
|
||||
|
||||
@ -362,7 +374,6 @@ public class DataResultFilterNode extends FilterNode {
|
||||
return defaultVisit(fileTypes);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected List<Action> defaultVisit(DisplayableItemNode ditem) {
|
||||
//preserve the default node's actions
|
||||
@ -460,8 +471,6 @@ public class DataResultFilterNode extends FilterNode {
|
||||
return openChild(fileTypes);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tell the originating ExplorerManager to display the given
|
||||
* dataModelNode.
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
* 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 Content content;
|
||||
|
||||
public ViewContextAction(String title, BlackboardArtifactNode node) {
|
||||
super(title);
|
||||
this.content = node.getLookup().lookup(Content.class);
|
||||
|
||||
}
|
||||
|
||||
public ViewContextAction(String title, AbstractFsContentNode<? extends AbstractFile> node) {
|
||||
@ -79,65 +79,70 @@ public class ViewContextAction extends AbstractAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// create a list of Content objects starting with content's
|
||||
// Image and ends with content
|
||||
ReverseHierarchyVisitor vtor = new ReverseHierarchyVisitor();
|
||||
List<Content> hierarchy = content.accept(vtor);
|
||||
Collections.reverse(hierarchy);
|
||||
EventQueue.invokeLater(() -> {
|
||||
// create a list of Content objects starting with content's
|
||||
// Image and ends with content
|
||||
ReverseHierarchyVisitor vtor = new ReverseHierarchyVisitor();
|
||||
List<Content> hierarchy = content.accept(vtor);
|
||||
Collections.reverse(hierarchy);
|
||||
|
||||
Node generated = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(hierarchy)), true);
|
||||
Children genChilds = generated.getChildren();
|
||||
Node generated = new DirectoryTreeFilterNode(new AbstractNode(new RootContentChildren(hierarchy)), true);
|
||||
Children genChilds = generated.getChildren();
|
||||
|
||||
final DirectoryTreeTopComponent dirTree = DirectoryTreeTopComponent.findInstance();
|
||||
TreeView dirTreeView = dirTree.getTree();
|
||||
ExplorerManager dirTreeExplorerManager = dirTree.getExplorerManager();
|
||||
Node dirTreeRootNode = dirTreeExplorerManager.getRootContext();
|
||||
Children dirChilds = dirTreeRootNode.getChildren();
|
||||
Children currentChildren = dirChilds.findChild(DataSourcesNode.NAME).getChildren();
|
||||
final DirectoryTreeTopComponent dirTree = DirectoryTreeTopComponent.findInstance();
|
||||
TreeView dirTreeView = dirTree.getTree();
|
||||
ExplorerManager dirTreeExplorerManager = dirTree.getExplorerManager();
|
||||
Node dirTreeRootNode = dirTreeExplorerManager.getRootContext();
|
||||
Children dirChilds = dirTreeRootNode.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
|
||||
for (int i = 0; i < genChilds.getNodesCount() - 1; i++) {
|
||||
Node currentGeneratedNode = genChilds.getNodeAt(i);
|
||||
for (int j = 0; j < currentChildren.getNodesCount(); j++) {
|
||||
Node currentDirectoryTreeNode = currentChildren.getNodeAt(j);
|
||||
if (currentGeneratedNode.getDisplayName().equals(currentDirectoryTreeNode.getDisplayName())) {
|
||||
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) {
|
||||
// Find the parent node of the content in the directory tree
|
||||
for (int i = 0; i < genChilds.getNodesCount() - 1; i++) {
|
||||
Node currentGeneratedNode = genChilds.getNodeAt(i);
|
||||
for (int j = 0; j < currentChildren.getNodesCount(); j++) {
|
||||
Node currentDirectoryTreeNode = currentChildren.getNodeAt(j);
|
||||
if (currentGeneratedNode.getDisplayName().equals(currentDirectoryTreeNode.getDisplayName())) {
|
||||
dirExplored = currentDirectoryTreeNode;
|
||||
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
|
||||
* 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>> {
|
||||
|
||||
List<Content> ret = new ArrayList<Content>();
|
||||
List<Content> ret = new ArrayList<>();
|
||||
|
||||
private List<Content> visitParentButDontAddMe(Content content) {
|
||||
Content parent = null;
|
||||
try {
|
||||
parent = content.getParent();
|
||||
} 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);
|
||||
}
|
||||
@ -234,7 +239,7 @@ public class ViewContextAction extends AbstractAction {
|
||||
try {
|
||||
parent = content.getParent();
|
||||
} 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);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.util.lookup.ServiceProviders;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.framework.AutopsyService;
|
||||
|
||||
@ServiceProviders(value = {@ServiceProvider(service = AutopsyService.class)})
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
|
||||
/**
|
||||
* Creates and handles closing of ImageWriter objects.
|
||||
* Currently, ImageWriter is only enabled for local disks, and local disks can
|
||||
* not be processed in multi user mode. If ImageWriter is ever enabled for multi user
|
||||
* cases this code will need to be revised.
|
||||
* Creates and handles closing of ImageWriter objects. Currently, ImageWriter is
|
||||
* only enabled for local disks, and local disks can not be processed in multi
|
||||
* user mode. If ImageWriter is ever enabled for multi user cases this code will
|
||||
* need to be revised.
|
||||
*/
|
||||
|
||||
@ServiceProvider(service = AutopsyService.class)
|
||||
public class ImageWriterService implements AutopsyService {
|
||||
|
||||
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.
|
||||
* @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
|
||||
// we're closing case resources so we don't need to worry about one showing up while
|
||||
// doing our close/cleanup.
|
||||
synchronized(imageWritersLock){
|
||||
synchronized (imageWritersLock) {
|
||||
ImageWriter writer = new ImageWriter(imageId, settings);
|
||||
writer.subscribeToEvents();
|
||||
imageWriters.add(writer);
|
||||
@ -66,54 +64,58 @@ public class ImageWriterService implements AutopsyService {
|
||||
|
||||
@Override
|
||||
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
|
||||
// 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
|
||||
// even though ingest is not complete so we will take that to mean that they
|
||||
// also don't want to wait for Image Writer.
|
||||
for(ImageWriter writer: imageWriters){
|
||||
for (ImageWriter writer : imageWriters) {
|
||||
writer.cancelIfNotStarted();
|
||||
}
|
||||
|
||||
// Test whether any finishImage tasks are in progress
|
||||
boolean jobsAreInProgress = false;
|
||||
for(ImageWriter writer: imageWriters){
|
||||
if(writer.jobIsInProgress()){
|
||||
for (ImageWriter writer : imageWriters) {
|
||||
if (writer.jobIsInProgress()) {
|
||||
jobsAreInProgress = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(jobsAreInProgress){
|
||||
if (jobsAreInProgress) {
|
||||
// If jobs are in progress, ask the user if they want to wait for them to complete
|
||||
NotifyDescriptor descriptor = new NotifyDescriptor.Confirmation(
|
||||
NbBundle.getMessage(this.getClass(), "ImageWriterService.shouldWait"),
|
||||
NbBundle.getMessage(this.getClass(), "ImageWriterService.localDisk"),
|
||||
NotifyDescriptor.YES_NO_OPTION,
|
||||
NotifyDescriptor.WARNING_MESSAGE);
|
||||
NbBundle.getMessage(this.getClass(), "ImageWriterService.shouldWait"),
|
||||
NbBundle.getMessage(this.getClass(), "ImageWriterService.localDisk"),
|
||||
NotifyDescriptor.YES_NO_OPTION,
|
||||
NotifyDescriptor.WARNING_MESSAGE);
|
||||
descriptor.setValue(NotifyDescriptor.NO_OPTION);
|
||||
Object response = DialogDisplayer.getDefault().notify(descriptor);
|
||||
|
||||
if(response == DialogDescriptor.NO_OPTION){
|
||||
if (response == DialogDescriptor.NO_OPTION) {
|
||||
// Cancel all the jobs
|
||||
for(ImageWriter writer: imageWriters){
|
||||
for (ImageWriter writer : imageWriters) {
|
||||
writer.cancelJob();
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for all finishImage jobs to complete. If the jobs got cancelled
|
||||
// this will be very fast.
|
||||
for(ImageWriter writer: imageWriters){
|
||||
for (ImageWriter writer : imageWriters) {
|
||||
writer.waitForJobToFinish();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Stop listening for events
|
||||
for(ImageWriter writer: imageWriters){
|
||||
for (ImageWriter writer : imageWriters) {
|
||||
writer.unsubscribeFromEvents();
|
||||
}
|
||||
|
||||
|
@ -393,6 +393,9 @@ public class IngestJobSettings {
|
||||
/**
|
||||
* 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 defaultSetting The default list of module names.
|
||||
*
|
||||
|
@ -138,9 +138,6 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
filterPanel.addPropertyChangeListener(l);
|
||||
@ -148,9 +145,6 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
|
||||
profilePanel.addPropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
filterPanel.removePropertyChangeListener(l);
|
||||
@ -158,9 +152,6 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
|
||||
profilePanel.removePropertyChangeListener(l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
saveTabByIndex(tabbedPane.getSelectedIndex());
|
||||
@ -189,17 +180,11 @@ public class IngestOptionsPanel extends IngestModuleGlobalSettingsPanel implemen
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void store() {
|
||||
saveSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void load() {
|
||||
filterPanel.load();
|
||||
|
@ -40,9 +40,6 @@ public class IngestOptionsPanelController extends OptionsPanelController {
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
private boolean changed;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void update() {
|
||||
getPanel().load();
|
||||
@ -69,9 +66,6 @@ public class IngestOptionsPanelController extends OptionsPanelController {
|
||||
return panel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
if (changed) {
|
||||
@ -85,57 +79,36 @@ public class IngestOptionsPanelController extends OptionsPanelController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void cancel() {
|
||||
getPanel().cancel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return getPanel().valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public JComponent getComponent(Lookup lkp) {
|
||||
return getPanel();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener pl) {
|
||||
pcs.addPropertyChangeListener(pl);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener pl) {
|
||||
pcs.removePropertyChangeListener(pl);
|
||||
|
@ -43,7 +43,6 @@ public abstract class ShortcutWizardDescriptorPanel implements WizardDescriptor.
|
||||
|
||||
/**
|
||||
* Whether or not the panel immediately following this one should be skipped
|
||||
* .
|
||||
*
|
||||
* @return true or false
|
||||
*/
|
||||
|
@ -21,19 +21,24 @@ package org.sleuthkit.autopsy.modules.embeddedfileextractor;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.lang.IllegalArgumentException;
|
||||
import java.lang.IndexOutOfBoundsException;
|
||||
import java.lang.NullPointerException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.apache.poi.OldFileFormatException;
|
||||
import org.apache.poi.POIXMLException;
|
||||
import org.apache.poi.hslf.model.Picture;
|
||||
import org.apache.poi.hslf.usermodel.PictureData;
|
||||
import org.apache.poi.hslf.usermodel.SlideShow;
|
||||
import org.apache.poi.hwpf.usermodel.Picture;
|
||||
import org.apache.poi.hslf.usermodel.HSLFPictureData;
|
||||
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.hwpf.HWPFDocument;
|
||||
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.util.RecordFormatException;
|
||||
import org.apache.poi.xslf.usermodel.XMLSlideShow;
|
||||
import org.apache.poi.xslf.usermodel.XSLFPictureData;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
@ -209,20 +214,31 @@ class ImageExtractor {
|
||||
* extracted.
|
||||
*/
|
||||
private List<ExtractedImage> extractImagesFromDoc(AbstractFile af) {
|
||||
List<org.apache.poi.hwpf.usermodel.Picture> listOfAllPictures;
|
||||
List<Picture> listOfAllPictures;
|
||||
|
||||
try {
|
||||
HWPFDocument doc = new HWPFDocument(new ReadContentInputStream(af));
|
||||
PicturesTable pictureTable = doc.getPicturesTable();
|
||||
listOfAllPictures = pictureTable.getAllPictures();
|
||||
} catch (OldFileFormatException | IOException ex) {
|
||||
// OldFileFormatException:
|
||||
// Thrown when the document version is unsupported (Word 95 and
|
||||
// older)
|
||||
|
||||
} catch (IOException | IllegalArgumentException |
|
||||
IndexOutOfBoundsException | NullPointerException ex) {
|
||||
// IOException:
|
||||
// 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;
|
||||
} catch (Throwable ex) {
|
||||
// instantiating POI containers throw RuntimeExceptions
|
||||
@ -241,7 +257,7 @@ class ImageExtractor {
|
||||
}
|
||||
List<ExtractedImage> listOfExtractedImages = new ArrayList<>();
|
||||
byte[] data = null;
|
||||
for (org.apache.poi.hwpf.usermodel.Picture picture : listOfAllPictures) {
|
||||
for (Picture picture : listOfAllPictures) {
|
||||
String fileName = picture.suggestFullFileName();
|
||||
try {
|
||||
data = picture.getContent();
|
||||
@ -319,17 +335,25 @@ class ImageExtractor {
|
||||
* extracted.
|
||||
*/
|
||||
private List<ExtractedImage> extractImagesFromPpt(AbstractFile af) {
|
||||
PictureData[] listOfAllPictures = null;
|
||||
List<HSLFPictureData> listOfAllPictures = null;
|
||||
|
||||
try {
|
||||
SlideShow ppt = new SlideShow(new ReadContentInputStream(af));
|
||||
HSLFSlideShow ppt = new HSLFSlideShow(new ReadContentInputStream(af));
|
||||
listOfAllPictures = ppt.getPictureData();
|
||||
} catch (OldFileFormatException | IOException ex) {
|
||||
// OldFileFormatException:
|
||||
// Thrown when the document version is unsupported
|
||||
} catch (IOException | IllegalArgumentException |
|
||||
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:
|
||||
// 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;
|
||||
} catch (Throwable ex) {
|
||||
@ -341,7 +365,7 @@ class ImageExtractor {
|
||||
// if no images are extracted from the PPT, return null, else initialize
|
||||
// the output folder for image extraction.
|
||||
String outputFolderPath;
|
||||
if (listOfAllPictures.length == 0) {
|
||||
if (listOfAllPictures.isEmpty()) {
|
||||
return null;
|
||||
} else {
|
||||
outputFolderPath = getOutputFolderPath(this.parentFileName);
|
||||
@ -355,26 +379,26 @@ class ImageExtractor {
|
||||
int i = 0;
|
||||
List<ExtractedImage> listOfExtractedImages = new ArrayList<>();
|
||||
byte[] data = null;
|
||||
for (PictureData pictureData : listOfAllPictures) {
|
||||
for (HSLFPictureData pictureData : listOfAllPictures) {
|
||||
|
||||
// Get image extension, generate image name, write image to the module
|
||||
// output folder, add it to the listOfExtractedImageAbstractFiles
|
||||
int type = pictureData.getType();
|
||||
PictureType type = pictureData.getType();
|
||||
String ext;
|
||||
switch (type) {
|
||||
case Picture.JPEG:
|
||||
case JPEG:
|
||||
ext = ".jpg"; //NON-NLS
|
||||
break;
|
||||
case Picture.PNG:
|
||||
case PNG:
|
||||
ext = ".png"; //NON-NLS
|
||||
break;
|
||||
case Picture.WMF:
|
||||
case WMF:
|
||||
ext = ".wmf"; //NON-NLS
|
||||
break;
|
||||
case Picture.EMF:
|
||||
case EMF:
|
||||
ext = ".emf"; //NON-NLS
|
||||
break;
|
||||
case Picture.PICT:
|
||||
case PICT:
|
||||
ext = ".pict"; //NON-NLS
|
||||
break;
|
||||
default:
|
||||
@ -406,7 +430,7 @@ class ImageExtractor {
|
||||
|
||||
try {
|
||||
XMLSlideShow pptx = new XMLSlideShow(new ReadContentInputStream(af));
|
||||
listOfAllPictures = pptx.getAllPictures();
|
||||
listOfAllPictures = pptx.getPictureData();
|
||||
} catch (POIXMLException | IOException ex) {
|
||||
// POIXMLException:
|
||||
// Thrown when document fails to load.
|
||||
@ -468,12 +492,30 @@ class ImageExtractor {
|
||||
try {
|
||||
Workbook xls = new HSSFWorkbook(new ReadContentInputStream(af));
|
||||
listOfAllPictures = xls.getAllPictures();
|
||||
} catch (OldFileFormatException | IOException ex) {
|
||||
// OldFileFormatException:
|
||||
// Thrown when the document version is unsupported
|
||||
} catch (IOException | LeftoverDataException |
|
||||
RecordFormatException | IllegalArgumentException |
|
||||
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:
|
||||
// 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;
|
||||
} catch (Throwable ex) {
|
||||
|
@ -169,9 +169,6 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
this.equalitySignComboBox.setSelectedIndex(2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void saveSettings() {
|
||||
try {
|
||||
@ -203,17 +200,11 @@ public final class FilesSetDefsPanel extends IngestModuleGlobalSettingsPanel imp
|
||||
ingestWarningLabel.setVisible(!isEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void store() {
|
||||
this.saveSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void load() {
|
||||
this.resetComponents();
|
||||
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.framework;
|
||||
package org.sleuthkit.autopsy.progress;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
@ -59,7 +59,7 @@ public final class LoggingProgressIndicator implements ProgressIndicator {
|
||||
|
||||
@Override
|
||||
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
|
||||
@ -68,8 +68,8 @@ public final class LoggingProgressIndicator implements ProgressIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(String message) {
|
||||
LOGGER.log(Level.INFO, "{0} finished", message);
|
||||
public void finish() {
|
||||
LOGGER.log(Level.INFO, "Finished");
|
||||
}
|
||||
|
||||
}
|
@ -16,11 +16,13 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.framework;
|
||||
package org.sleuthkit.autopsy.progress;
|
||||
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Frame;
|
||||
import java.awt.event.ActionListener;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import javax.annotation.concurrent.ThreadSafe;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.SwingUtilities;
|
||||
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
|
||||
* 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 {
|
||||
|
||||
private final Frame parent;
|
||||
private final String title;
|
||||
private final ProgressPanel progressPanel;
|
||||
private final Dialog dialog;
|
||||
private final Object[] buttonLabels;
|
||||
private final Object focusedButtonLabel;
|
||||
private final ActionListener buttonListener;
|
||||
private Dialog dialog;
|
||||
@GuardedBy("this")
|
||||
private boolean cancelling;
|
||||
|
||||
/**
|
||||
* 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) {
|
||||
this.parent = parent;
|
||||
this.title = title;
|
||||
progressPanel = new ProgressPanel();
|
||||
DialogDescriptor dialogDescriptor = new DialogDescriptor(
|
||||
progressPanel,
|
||||
title,
|
||||
true,
|
||||
buttonLabels,
|
||||
focusedButtonLabel,
|
||||
DialogDescriptor.BOTTOM_ALIGN,
|
||||
HelpCtx.DEFAULT_HELP,
|
||||
buttonListener);
|
||||
dialog = DialogDisplayer.getDefault().createDialog(dialogDescriptor);
|
||||
progressPanel.setIndeterminate(true);
|
||||
this.buttonLabels = buttonLabels;
|
||||
this.focusedButtonLabel = focusedButtonLabel;
|
||||
this.buttonListener = buttonListener;
|
||||
}
|
||||
|
||||
@ -76,32 +79,12 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
*/
|
||||
public ModalDialogProgressIndicator(Frame parent, String title) {
|
||||
this.parent = parent;
|
||||
this.title = title;
|
||||
progressPanel = new ProgressPanel();
|
||||
dialog = new JDialog(parent, title, true);
|
||||
dialog.add(progressPanel);
|
||||
dialog.pack();
|
||||
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;
|
||||
progressPanel.setIndeterminate(true);
|
||||
this.buttonLabels = null;
|
||||
this.focusedButtonLabel = null;
|
||||
this.buttonListener = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,14 +95,13 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
* @param totalWorkUnits The total number of work units.
|
||||
*/
|
||||
@Override
|
||||
public void start(String message, int totalWorkUnits) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(false);
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setMaximum(totalWorkUnits);
|
||||
}
|
||||
public synchronized void start(String message, int totalWorkUnits) {
|
||||
cancelling = false;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setIndeterminate(false);
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setMaximum(totalWorkUnits);
|
||||
displayDialog();
|
||||
});
|
||||
}
|
||||
|
||||
@ -130,13 +112,27 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
* @param message The initial progress message.
|
||||
*/
|
||||
@Override
|
||||
public void start(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(true);
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
public synchronized void start(String message) {
|
||||
cancelling = false;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setIndeterminate(true);
|
||||
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.
|
||||
*/
|
||||
@Override
|
||||
public void switchToIndeterminate(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(true);
|
||||
public synchronized void switchToIndeterminate(String message) {
|
||||
if (!cancelling) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setIndeterminate(true);
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -166,16 +161,15 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
* @param totalWorkUnits The total number of work units to be completed.
|
||||
*/
|
||||
@Override
|
||||
public void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setInderminate(false);
|
||||
public synchronized void switchToDeterminate(String message, int workUnitsCompleted, int totalWorkUnits) {
|
||||
if (!cancelling) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setIndeterminate(false);
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setMaximum(totalWorkUnits);
|
||||
progressPanel.setCurrent(workUnitsCompleted);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,13 +178,12 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
* @param message The progress message.
|
||||
*/
|
||||
@Override
|
||||
public void progress(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
public synchronized void progress(String message) {
|
||||
if (!cancelling) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -201,13 +194,12 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
* @param workUnitsCompleted Number of work units completed so far.
|
||||
*/
|
||||
@Override
|
||||
public void progress(int workUnitsCompleted) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
public synchronized void progress(int workUnitsCompleted) {
|
||||
if (!cancelling) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setCurrent(workUnitsCompleted);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -219,29 +211,52 @@ public final class ModalDialogProgressIndicator implements ProgressIndicator {
|
||||
* @param workUnitsCompleted Number of work units completed so far.
|
||||
*/
|
||||
@Override
|
||||
public void progress(String message, int workUnitsCompleted) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
public synchronized void progress(String message, int workUnitsCompleted) {
|
||||
if (!cancelling) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
progressPanel.setMessage(message);
|
||||
progressPanel.setCurrent(workUnitsCompleted);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress indicator when the task is completed.
|
||||
*
|
||||
* @param message The finished message.
|
||||
*/
|
||||
@Override
|
||||
public void finish(String message) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressPanel.setMessage(message);
|
||||
}
|
||||
public synchronized void finish() {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
this.dialog.setVisible(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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
|
||||
@ -46,6 +46,7 @@ public interface ProgressIndicator {
|
||||
/**
|
||||
* Switches the progress indicator to indeterminate mode (the total number
|
||||
* of work units to be completed is unknown).
|
||||
*
|
||||
* @param message The initial progress message.
|
||||
*/
|
||||
public void switchToIndeterminate(String message);
|
||||
@ -54,7 +55,7 @@ public interface ProgressIndicator {
|
||||
* Switches the progress indicator to determinate mode (the total number of
|
||||
* 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 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.
|
||||
*
|
||||
* @param message The finished message.
|
||||
*/
|
||||
void finish(String message);
|
||||
void finish();
|
||||
|
||||
}
|
@ -42,7 +42,7 @@
|
||||
<Component class="javax.swing.JLabel" name="progressMessage">
|
||||
<Properties>
|
||||
<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, "{key}")"/>
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/progress/Bundle.properties" key="ProgressPanel.progressMessage.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
@ -16,7 +16,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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.
|
||||
@ -35,7 +35,7 @@ class ProgressPanel extends javax.swing.JPanel {
|
||||
this.progressMessage.setText(message);
|
||||
}
|
||||
|
||||
void setInderminate(boolean indeterminate) {
|
||||
void setIndeterminate(boolean indeterminate) {
|
||||
this.progressBar.setIndeterminate(indeterminate);
|
||||
}
|
||||
|
@ -16,9 +16,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* 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.
|
||||
@ -54,7 +54,7 @@ public class SilentProgressIndicator implements ProgressIndicator {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish(String message) {
|
||||
public void finish() {
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Copyright 2013-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -80,15 +80,15 @@ class ReportExcel implements TableReportModule {
|
||||
Font titleFont = wb.createFont();
|
||||
titleFont.setFontHeightInPoints((short) 12);
|
||||
titleStyle.setFont(titleFont);
|
||||
titleStyle.setAlignment(CellStyle.ALIGN_LEFT);
|
||||
titleStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
titleStyle.setWrapText(true);
|
||||
|
||||
setStyle = wb.createCellStyle();
|
||||
Font setFont = wb.createFont();
|
||||
setFont.setFontHeightInPoints((short) 14);
|
||||
setFont.setBoldweight((short) 10);
|
||||
setFont.setBold(true);
|
||||
setStyle.setFont(setFont);
|
||||
setStyle.setAlignment(CellStyle.ALIGN_LEFT);
|
||||
setStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
setStyle.setWrapText(true);
|
||||
|
||||
elementStyle = wb.createCellStyle();
|
||||
@ -96,7 +96,7 @@ class ReportExcel implements TableReportModule {
|
||||
Font elementFont = wb.createFont();
|
||||
elementFont.setFontHeightInPoints((short) 14);
|
||||
elementStyle.setFont(elementFont);
|
||||
elementStyle.setAlignment(CellStyle.ALIGN_LEFT);
|
||||
elementStyle.setAlignment(HorizontalAlignment.LEFT);
|
||||
elementStyle.setWrapText(true);
|
||||
|
||||
writeSummaryWorksheet();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
@ -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";
|
||||
}
|
||||
}
|
@ -21,8 +21,8 @@ package org.sleuthkit.autopsy.test;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.framework.AutopsyService;
|
||||
import org.sleuthkit.autopsy.framework.ProgressIndicator;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
import org.sleuthkit.autopsy.progress.ProgressIndicator;
|
||||
|
||||
/**
|
||||
* An implementation of the Autopsy service interface used for test purposes.
|
||||
@ -53,7 +53,7 @@ public class TestAutopsyService implements AutopsyService {
|
||||
progressIndicator.progress(80);
|
||||
Thread.sleep(1000L);
|
||||
progressIndicator.progress(100);
|
||||
progressIndicator.finish("First task completed by Test Autopsy Service.");
|
||||
progressIndicator.finish();
|
||||
progressIndicator.start("Test Autopsy Service doing second task...");
|
||||
for (int i = 0; i < 10000; ++i) {
|
||||
logger.log(Level.INFO, "Test Autopsy Service simulating work on second task");
|
||||
@ -62,7 +62,7 @@ public class TestAutopsyService implements AutopsyService {
|
||||
break;
|
||||
}
|
||||
}
|
||||
progressIndicator.finish("Second task completed by Test Autopsy Service.");
|
||||
progressIndicator.finish();
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.INFO, "Test Autopsy Service interrupted (cancelled) while doing first task, cancel requested = {0}", context.cancelRequested());
|
||||
}
|
||||
|
@ -100,11 +100,15 @@ public class EventRootNode extends DisplayableItemNode {
|
||||
*/
|
||||
if (eventIDs.size() < MAX_EVENTS_TO_DISPLAY) {
|
||||
for (Long eventId: eventIDs){
|
||||
nodesMap.put(eventId, createNode(eventId));
|
||||
toPopulate.add(eventId);
|
||||
if (!nodesMap.containsKey(eventId)) {
|
||||
nodesMap.put(eventId, createNode(eventId));
|
||||
}
|
||||
toPopulate.add(eventId);
|
||||
}
|
||||
} else {
|
||||
nodesMap.put(-1L, createNode(-1L));
|
||||
if (!nodesMap.containsKey(-1L)) {
|
||||
nodesMap.put(-1L, createNode(-1L));
|
||||
}
|
||||
toPopulate.add(-1L);
|
||||
}
|
||||
return true;
|
||||
|
@ -28,8 +28,8 @@
|
||||
<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.apache.poi" name="poi-excelant" rev="3.8"/>
|
||||
<dependency conf="autopsy_core->*" org="org.apache.poi" name="poi-scratchpad" 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.15"/>
|
||||
|
||||
<!-- process and system monitoring, note: matching native libs pulled from thirdparty -->
|
||||
<dependency conf="autopsy_core->*" org="org.fusesource" name="sigar" rev="1.6.4" />
|
||||
|
@ -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-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.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-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
|
||||
@ -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.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.poi-3.8.jar=release/modules/ext/poi-3.8.jar
|
||||
file.reference.poi-excelant-3.8.jar=release/modules/ext/poi-excelant-3.8.jar
|
||||
file.reference.poi-ooxml-3.8.jar=release/modules/ext/poi-ooxml-3.8.jar
|
||||
file.reference.poi-ooxml-schemas-3.8.jar=release/modules/ext/poi-ooxml-schemas-3.8.jar
|
||||
file.reference.poi-scratchpad-3.8.jar=release/modules/ext/poi-scratchpad-3.8.jar
|
||||
file.reference.poi-3.15.jar=release/modules/ext/poi-3.15.jar
|
||||
file.reference.poi-excelant-3.15.jar=release/modules/ext/poi-excelant-3.15.jar
|
||||
file.reference.poi-ooxml-3.15.jar=release/modules/ext/poi-ooxml-3.15.jar
|
||||
file.reference.poi-ooxml-schemas-3.15.jar=release/modules/ext/poi-ooxml-schemas-3.15.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.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
|
||||
@ -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.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.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.compilerargs=-Xlint -Xlint:-serial
|
||||
javadoc.reference.commons-csv-1.4.jar=release/modules/ext/commons-csv-1.4-javadoc.jar
|
||||
|
@ -700,16 +700,16 @@
|
||||
<binary-origin>release/modules/ext/sigar-1.6.4.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/xmlbeans-2.3.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/xmlbeans-2.3.0.jar</binary-origin>
|
||||
<runtime-relative-path>ext/xmlbeans-2.6.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/xmlbeans-2.6.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jna-3.4.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jna-3.4.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/poi-ooxml-schemas-3.8.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.8.jar</binary-origin>
|
||||
<runtime-relative-path>ext/poi-ooxml-schemas-3.15.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-ooxml-schemas-3.15.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/poi-ooxml-3.8.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-ooxml-3.8.jar</binary-origin>
|
||||
<runtime-relative-path>ext/poi-ooxml-3.15.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-ooxml-3.15.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
<binary-origin>release/modules/ext/stax-api-1.0.1.jar</binary-origin>
|
||||
</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>
|
||||
<runtime-relative-path>ext/servlet-api-2.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/servlet-api-2.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/poi-excelant-3.8.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-excelant-3.8.jar</binary-origin>
|
||||
<runtime-relative-path>ext/poi-excelant-3.15.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-excelant-3.15.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/poi-scratchpad-3.8.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-scratchpad-3.8.jar</binary-origin>
|
||||
<runtime-relative-path>ext/poi-scratchpad-3.15.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-scratchpad-3.15.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/commons-codec-1.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-codec-1.5.jar</binary-origin>
|
||||
<runtime-relative-path>ext/commons-codec-1.10.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-codec-1.10.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/poi-3.8.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-3.8.jar</binary-origin>
|
||||
<runtime-relative-path>ext/poi-3.15.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/poi-3.15.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/controlsfx-8.40.11.jar</runtime-relative-path>
|
||||
|
@ -7,7 +7,7 @@
|
||||
</configurations>
|
||||
<dependencies>
|
||||
<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="com.mchange" name="c3p0" rev="0.9.5"/>
|
||||
<dependency conf="experimental->default" org="com.fasterxml.jackson.core" name="jackson-core" rev="2.7.0"/>
|
||||
|
@ -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.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.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.compilerargs=-Xlint -Xlint:-serial
|
||||
javadoc.reference.LGoodDatePicker-4.3.1.jar=release/modules/ext/LGoodDatePicker-4.3.1-javadoc.jar
|
||||
|
@ -132,8 +132,8 @@
|
||||
<binary-origin>release/modules/ext/LGoodDatePicker-4.3.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/tika-core-1.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/tika-core-1.5.jar</binary-origin>
|
||||
<runtime-relative-path>ext/tika-core-1.14.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/tika-core-1.14.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jackson-core-2.7.0.jar</runtime-relative-path>
|
||||
|
@ -39,10 +39,11 @@ import javax.swing.SwingWorker;
|
||||
import javax.swing.event.ListSelectionEvent;
|
||||
import javax.swing.table.DefaultTableModel;
|
||||
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.StartupWindowProvider;
|
||||
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.
|
||||
@ -295,18 +296,12 @@ public final class AutoIngestCasePanel extends JPanel {
|
||||
protected void done() {
|
||||
try {
|
||||
get();
|
||||
} catch (InterruptedException 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.getMessage(),
|
||||
org.openide.util.NbBundle.getMessage(AutoIngestCasePanel.class, "ReviewModeCasePanel.cannotOpenCase"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
} 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);
|
||||
} catch (InterruptedException | ExecutionException ex) {
|
||||
if (null != ex.getCause() && !(ex.getCause() instanceof CaseActionCancelledException)) {
|
||||
logger.log(Level.SEVERE, String.format("Error opening case with metadata file path %s", caseMetadataFilePath), ex); //NON-NLS
|
||||
MessageNotifyUtil.Message.error(ex.getCause().getLocalizedMessage());
|
||||
}
|
||||
StartupWindowProvider.getInstance().open();
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
|
@ -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.SharedConfiguration;
|
||||
import org.sleuthkit.autopsy.experimental.configuration.SharedConfiguration.SharedConfigurationException;
|
||||
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.framework.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.datasourceprocessors.AutoIngestDataSourceProcessor.AutoIngestDataSourceProcessorException;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJob;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJob.CancellationReason;
|
||||
import org.sleuthkit.autopsy.ingest.IngestJobSettings;
|
||||
|
@ -39,10 +39,10 @@ import org.xml.sax.SAXException;
|
||||
public final class AutopsyManifestFileParser implements ManifestFileParser {
|
||||
|
||||
private static final String MANIFEST_FILE_NAME_SIGNATURE = "_Manifest.xml";
|
||||
private static final String ROOT_ELEM_TAG_NAME = "Manifest";
|
||||
private static final String CASE_NAME_XPATH = "/Manifest/Collection/Name/text()";
|
||||
private static final String DEVICE_ID_XPATH = "/Manifest/Collection/Image/ID/text()";
|
||||
private static final String DATA_SOURCE_NAME_XPATH = "/Manifest/Collection/Image/Name/text()";
|
||||
private static final String ROOT_ELEM_TAG_NAME = "AutopsyManifest";
|
||||
private static final String CASE_NAME_XPATH = "/AutopsyManifest/CaseName/text()";
|
||||
private static final String DEVICE_ID_XPATH = "/AutopsyManifest/DeviceId/text()";
|
||||
private static final String DATA_SOURCE_NAME_XPATH = "/AutopsyManifest/DataSource/text()";
|
||||
|
||||
@Override
|
||||
public boolean fileIsManifest(Path filePath) {
|
||||
@ -62,10 +62,6 @@ public final class AutopsyManifestFileParser implements ManifestFileParser {
|
||||
|
||||
@Override
|
||||
public Manifest parse(Path filePath) throws ManifestFileParserException {
|
||||
if (!fileIsManifest(filePath)) {
|
||||
throw new ManifestFileParserException(String.format("%s not recognized as a manifest", filePath));
|
||||
}
|
||||
|
||||
try {
|
||||
Document doc = this.createManifestDOM(filePath);
|
||||
XPath xpath = XPathFactory.newInstance().newXPath();
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Copyright 2015-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
public final static class ManifestFileParserException extends Exception {
|
||||
|
@ -35,6 +35,7 @@ import org.openide.util.actions.Presenter;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.core.Installer;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryController;
|
||||
import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule;
|
||||
@ -64,7 +65,7 @@ public final class OpenAction extends CallableSystemAction implements Presenter.
|
||||
toolbarButton.addActionListener(actionEvent -> performAction());
|
||||
pcl = (PropertyChangeEvent evt) -> {
|
||||
if (evt.getPropertyName().equals(Case.Events.CURRENT_CASE.toString())) {
|
||||
setEnabled(evt.getNewValue() != null);
|
||||
setEnabled(RuntimeProperties.runningWithGUI() && evt.getNewValue() != null);
|
||||
}
|
||||
};
|
||||
Case.addPropertyChangeListener(pcl);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-16 Basis Technology Corp.
|
||||
* Copyright 2011-17 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
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
|
||||
public int compare(DrawableGroup o1, DrawableGroup o2) {
|
||||
|
@ -5,10 +5,6 @@
|
||||
<!-- module dependencies -->
|
||||
<conf name="autopsy"/>
|
||||
|
||||
<!-- Solr index upgrade tool dependencies -->
|
||||
<conf name="solr4to5"/>
|
||||
<conf name="solr5to6"/>
|
||||
|
||||
<!-- Solr server dependencies -->
|
||||
<conf name="solr-libs"/>
|
||||
<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-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 -->
|
||||
<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"/>
|
||||
|
@ -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-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-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-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
|
||||
|
@ -213,7 +213,7 @@ Server.queryNumFileChunks.exception.msg=Error getting number of file chunks,
|
||||
Server.query.exception.msg=Error running query\: {0}
|
||||
Server.query2.exception.msg=Error running 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.cantOpen.msg=Could not create or open index
|
||||
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
|
||||
GlobalEditListPanel.editWordButton.text=Edit Keyword
|
||||
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.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>
|
||||
|
||||
|
@ -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.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)
|
||||
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
|
||||
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
|
||||
|
@ -19,6 +19,9 @@
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
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.Collection;
|
||||
import java.util.HashMap;
|
||||
@ -32,6 +35,7 @@ import java.util.stream.Collectors;
|
||||
import javax.annotation.concurrent.GuardedBy;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
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.SolrRequest.METHOD;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
@ -337,7 +341,6 @@ class HighlightedText implements IndexedText {
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
|
||||
try {
|
||||
loadPageInfo(); //inits once
|
||||
SolrQuery q = new SolrQuery();
|
||||
@ -349,15 +352,22 @@ class HighlightedText implements IndexedText {
|
||||
contentIdStr += "0".equals(chunkID) ? "" : "_" + chunkID;
|
||||
}
|
||||
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 the query is literal try to get solr to do the highlighting
|
||||
final String highlightQuery = keywords.stream()
|
||||
.map(HighlightedText::constructEscapedSolrQuery)
|
||||
.collect(Collectors.joining(" "));
|
||||
|
||||
q.setQuery(highlightQuery);
|
||||
q.addField(Server.Schema.TEXT.toString());
|
||||
q.addField(highlightField);
|
||||
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
|
||||
|
||||
//tune the highlighter
|
||||
@ -369,8 +379,12 @@ class HighlightedText implements IndexedText {
|
||||
//docs says makes sense for the original Highlighter only, but not really
|
||||
q.setParam("hl.maxAnalyzedChars", Server.HL_ANALYZE_CHARS_UNLIMITED); //NON-NLS
|
||||
} else {
|
||||
/*
|
||||
* if the query is not literal just pull back the text. We will
|
||||
* do the highlighting in autopsy.
|
||||
*/
|
||||
q.setQuery(filterQuery);
|
||||
q.addField(Server.Schema.CONTENT_STR.toString());
|
||||
q.addField(highlightField);
|
||||
}
|
||||
|
||||
QueryResponse response = solrServer.query(q, METHOD.POST);
|
||||
@ -383,9 +397,7 @@ class HighlightedText implements IndexedText {
|
||||
}
|
||||
String highlightedContent;
|
||||
Map<String, Map<String, List<String>>> responseHighlight = response.getHighlighting();
|
||||
String highlightField = isLiteral
|
||||
? LuceneQuery.HIGHLIGHT_FIELD
|
||||
: Server.Schema.CONTENT_STR.toString();
|
||||
|
||||
if (responseHighlight == null) {
|
||||
highlightedContent = attemptManualHighlighting(response.getResults(), highlightField, keywords);
|
||||
} else {
|
||||
@ -433,6 +445,7 @@ class HighlightedText implements IndexedText {
|
||||
return 0;
|
||||
}
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
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) {
|
||||
//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);
|
||||
int textOffset = 0;
|
||||
int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, textOffset);
|
||||
int searchOffset = 0;
|
||||
int hitOffset = StringUtils.indexOfIgnoreCase(text, escapedKeyword, searchOffset);
|
||||
while (hitOffset != -1) {
|
||||
// Append the portion of text up to (but not including) the hit.
|
||||
highlightedText.append(text.substring(textOffset, hitOffset));
|
||||
// Add in the highlighting around the keyword.
|
||||
highlightedText.append(HIGHLIGHT_PRE);
|
||||
highlightedText.append(keyword);
|
||||
highlightedText.append(HIGHLIGHT_POST);
|
||||
// Advance the search offset past the keyword.
|
||||
searchOffset = hitOffset + escapedKeyword.length();
|
||||
|
||||
// Advance the text offset past the keyword.
|
||||
textOffset = hitOffset + escapedKeyword.length();
|
||||
//record the location of the hit, possibly merging it with other hits
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* 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.logging.Level;
|
||||
import net.htmlparser.jericho.Attributes;
|
||||
import net.htmlparser.jericho.Config;
|
||||
import net.htmlparser.jericho.LoggerProvider;
|
||||
import net.htmlparser.jericho.Renderer;
|
||||
import net.htmlparser.jericho.Source;
|
||||
import net.htmlparser.jericho.StartTag;
|
||||
@ -50,6 +52,11 @@ class HtmlTextExtractor extends FileTextExtractor {
|
||||
"text/javascript" //NON-NLS
|
||||
);
|
||||
|
||||
static {
|
||||
// Disable Jericho HTML Parser log messages.
|
||||
Config.LoggerProvider = LoggerProvider.DISABLED;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isContentTypeSpecific() {
|
||||
return true;
|
||||
|
@ -27,7 +27,7 @@ import java.util.List;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
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.
|
||||
|
@ -315,16 +315,16 @@ class Ingester {
|
||||
*
|
||||
* @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<>();
|
||||
params.put(Server.Schema.ID.toString(), Long.toString(af.getId()));
|
||||
params.put(Server.Schema.ID.toString(), Long.toString(file.getId()));
|
||||
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) {
|
||||
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.FILE_NAME.toString(), af.getName());
|
||||
params.put(Server.Schema.FILE_NAME.toString(), file.getName());
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Copyright 2011-2017 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -446,7 +446,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -561,7 +561,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
|
||||
return;
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
|
||||
|
@ -187,7 +187,7 @@ public class Server {
|
||||
private int currentSolrServerPort = 0;
|
||||
private int currentSolrStopPort = 0;
|
||||
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";
|
||||
|
||||
public enum CORE_EVT_STATES {
|
||||
@ -636,7 +636,7 @@ public class Server {
|
||||
* Creates/opens a Solr core (index) for a case.
|
||||
*
|
||||
* @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
|
||||
* creating/opening the core.
|
||||
@ -713,7 +713,6 @@ public class Server {
|
||||
/**
|
||||
* ** end single-case specific methods ***
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deletes the keyword search core for a case.
|
||||
*
|
||||
@ -721,46 +720,41 @@ public class Server {
|
||||
*/
|
||||
@NbBundle.Messages({
|
||||
"# {0} - core name", "Server.deleteCore.exception.msg=Failed to delete Solr core {0}",})
|
||||
void deleteCore(String coreName) 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();
|
||||
void deleteCore(String coreName, Case.CaseType caseType) throws KeywordSearchServiceException {
|
||||
try {
|
||||
if (null != currentCore) {
|
||||
if (currentCore.getName().equals(coreName)) {
|
||||
// close current core first
|
||||
closeCore();
|
||||
}
|
||||
HttpSolrServer solrServer;
|
||||
if (caseType == CaseType.SINGLE_USER_CASE) {
|
||||
Integer localSolrServerPort = Integer.decode(ModuleSettings.getConfigSetting(PROPERTIES_FILE, PROPERTIES_CURRENT_SERVER_PORT));
|
||||
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);
|
||||
org.apache.solr.client.solrj.request.CoreAdminRequest.unloadCore(coreName, true, true, solrServer);
|
||||
} catch (SolrServerException | IOException ex) {
|
||||
CoreAdminResponse response = CoreAdminRequest.getStatus(coreName, solrServer);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates/opens a Solr core (index) for a case.
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
@ -780,7 +774,7 @@ public class Server {
|
||||
connectToSolrServer(currentSolrServer);
|
||||
|
||||
} 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 {
|
||||
@ -891,8 +885,8 @@ public class Server {
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute query that gets only number of all Solr file chunks (not
|
||||
* logical files) indexed without actually returning the content.
|
||||
* Execute query that gets only number of all Solr file chunks (not logical
|
||||
* files) indexed without actually returning the content.
|
||||
*
|
||||
* @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
|
||||
* (files and chunks) without actually returning the documents
|
||||
* Execute query that gets only number of all Solr documents indexed (files
|
||||
* and chunks) without actually returning the documents
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @param fileID file id of the original file broken into chunks and
|
||||
* indexed
|
||||
* @param fileID file id of the original file broken into chunks and indexed
|
||||
*
|
||||
* @return int representing number of indexed file chunks, 0 if there is
|
||||
* no chunks
|
||||
* @return int representing number of indexed file chunks, 0 if there is no
|
||||
* chunks
|
||||
*
|
||||
* @throws KeywordSearchModuleException
|
||||
* @throws NoOpenCoreException
|
||||
@ -1206,8 +1199,7 @@ public class Server {
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the index files folder for a Solr core
|
||||
* exists.
|
||||
* Determines whether or not the index files folder for a Solr core exists.
|
||||
*
|
||||
* @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)
|
||||
* indexed without actually returning the files
|
||||
*
|
||||
* @return int representing number of indexed files (entire files,
|
||||
* not chunks)
|
||||
* @return int representing number of indexed files (entire files, not
|
||||
* chunks)
|
||||
*
|
||||
* @throws SolrServerException
|
||||
*/
|
||||
@ -1447,11 +1439,11 @@ public class Server {
|
||||
/**
|
||||
* Execute query that gets number of indexed file chunks for a file
|
||||
*
|
||||
* @param contentID file id of the original file broken into chunks
|
||||
* and indexed
|
||||
* @param contentID file id of the original file broken into chunks and
|
||||
* indexed
|
||||
*
|
||||
* @return int representing number of indexed file chunks, 0 if there
|
||||
* is no chunks
|
||||
* @return int representing number of indexed file chunks, 0 if there is
|
||||
* no chunks
|
||||
*
|
||||
* @throws SolrServerException
|
||||
*/
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.keywordsearch;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
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.CaseMetadata;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
import org.sleuthkit.autopsy.coreutils.FileUtil;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.framework.AutopsyService;
|
||||
import org.sleuthkit.autopsy.framework.ProgressIndicator;
|
||||
import org.sleuthkit.autopsy.appservices.AutopsyService;
|
||||
import org.sleuthkit.autopsy.progress.ProgressIndicator;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact;
|
||||
@ -50,7 +52,8 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
* text indexing and search.
|
||||
*/
|
||||
@ServiceProviders(value = {
|
||||
@ServiceProvider(service = KeywordSearchService.class),
|
||||
@ServiceProvider(service = KeywordSearchService.class)
|
||||
,
|
||||
@ServiceProvider(service = AutopsyService.class)}
|
||||
)
|
||||
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.
|
||||
*
|
||||
* @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
|
||||
public void deleteTextIndex(CaseMetadata metadata) throws KeywordSearchServiceException {
|
||||
String caseDirectory = metadata.getCaseDirectory();
|
||||
@ -163,13 +167,23 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
|
||||
String currentSolr = IndexFinder.getCurrentSolrVersion();
|
||||
for (Index index : indexMetadata.getIndexes()) {
|
||||
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
|
||||
logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class, "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
|
||||
throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class, "SolrSearchService.exceptionMessage.noCurrentSolrCore"));
|
||||
logger.log(Level.WARNING, NbBundle.getMessage(SolrSearchService.class,
|
||||
"SolrSearchService.exceptionMessage.noCurrentSolrCore"));
|
||||
throw new KeywordSearchServiceException(NbBundle.getMessage(SolrSearchService.class,
|
||||
"SolrSearchService.exceptionMessage.noCurrentSolrCore"));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -200,6 +214,10 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
|
||||
"SolrSearch.openCore.msg=Opening text index",
|
||||
"SolrSearch.complete.msg=Text index successfully opened"})
|
||||
public void openCaseResources(CaseContext context) throws AutopsyServiceException {
|
||||
if (context.cancelRequested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProgressIndicator progress = context.getProgressIndicator();
|
||||
int totalNumProgressUnits = 7;
|
||||
int progressUnitsCompleted = 0;
|
||||
|
@ -174,13 +174,10 @@ class StringsTextExtractor extends FileTextExtractor {
|
||||
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
|
||||
*
|
||||
* @param content to extract strings from
|
||||
* @param outputCharset target charset to encode into bytes and index
|
||||
* as, e.g. UTF-8
|
||||
*
|
||||
* @param content Content object from which to extract strings.
|
||||
*/
|
||||
private EnglishOnlyStream(AbstractFile content) {
|
||||
this.content = content;
|
||||
@ -378,8 +375,10 @@ class StringsTextExtractor extends FileTextExtractor {
|
||||
private final AbstractFile content;
|
||||
private final byte[] oneCharBuf = new byte[1];
|
||||
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 byte[] fileReadBuff = new byte[FILE_BUF_SIZE];
|
||||
private long fileReadOffset = 0L;
|
||||
|
@ -57,7 +57,6 @@ class TikaTextExtractor extends FileTextExtractor {
|
||||
@Override
|
||||
public void logWarning(final String msg, Exception ex) {
|
||||
KeywordSearch.getTikaLogger().log(Level.WARNING, msg, ex);
|
||||
logger.log(Level.WARNING, msg, ex); //NON-NLS }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
23
NEWS.txt
23
NEWS.txt
@ -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 --------------
|
||||
Improvements:
|
||||
- Support for slack space on files (as separate virtual files) to enable keyword searching and other analysis.
|
||||
|
@ -17,9 +17,11 @@
|
||||
</target>
|
||||
|
||||
<!-- 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">
|
||||
<manifestclasspath property="tem.classpath" jarfile="allJarsInUse.jar">
|
||||
<manifestclasspath property="tem.classpath" jarfile="allJarsInUse.jar" maxParentLevels="5">
|
||||
<classpath refid="test.${regression}.run.cp"/>
|
||||
</manifestclasspath>
|
||||
<jar destfile="allJarsInUse.jar" basedir="build/classes">
|
||||
|
@ -59,11 +59,9 @@ public class AutopsyTestCases {
|
||||
private long start;
|
||||
|
||||
/**
|
||||
* This method is used to escape file/directory path. Example:
|
||||
* \\NetworkLocation\foo\bar get escaped to \\\\NetworkLocation\foo\bar so
|
||||
* that it can be used as intended.
|
||||
* Escapes the slashes in a file or directory path.
|
||||
*
|
||||
* @param path
|
||||
* @param path The path to be escaped.
|
||||
*
|
||||
* @return escaped path the the file/directory location.
|
||||
*/
|
||||
@ -78,7 +76,7 @@ public class AutopsyTestCases {
|
||||
}
|
||||
}
|
||||
|
||||
public AutopsyTestCases () {
|
||||
public AutopsyTestCases() {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
@ -107,7 +105,10 @@ public class AutopsyTestCases {
|
||||
|
||||
public void testStartAddImageFileDataSource() {
|
||||
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
|
||||
JToggleButtonOperator jtbo = new JToggleButtonOperator(wo, 0);
|
||||
jtbo.clickMouse();
|
||||
@ -123,7 +124,10 @@ public class AutopsyTestCases {
|
||||
|
||||
public void testStartAddLogicalFilesDataSource() {
|
||||
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
|
||||
JToggleButtonOperator jtbo = new JToggleButtonOperator(wo, 2);
|
||||
jtbo.clickMouse();
|
||||
@ -139,7 +143,7 @@ public class AutopsyTestCases {
|
||||
}
|
||||
|
||||
public void testAddSourceWizard1() {
|
||||
WizardOperator wo = new WizardOperator("Add Data");
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
while (!wo.btFinish().isEnabled()) {
|
||||
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();
|
||||
|
||||
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);
|
||||
int row = jto.findCellRow("Hash Lookup", 2, 0);
|
||||
jto.clickOnCell(row, 1);
|
||||
@ -201,7 +208,10 @@ public class AutopsyTestCases {
|
||||
|
||||
public void testConfigureIngest2() {
|
||||
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);
|
||||
int row = jto.findCellRow("Keyword Search", 2, 0);
|
||||
jto.clickOnCell(row, 1);
|
||||
@ -234,7 +244,7 @@ public class AutopsyTestCases {
|
||||
}
|
||||
JButtonOperator jbo2 = new JButtonOperator(jdo, "OK", 0);
|
||||
jbo2.pushNoBlock();
|
||||
WizardOperator wo = new WizardOperator("Add Data");
|
||||
WizardOperator wo = new WizardOperator("Add Data Source");
|
||||
new Timeout("pausing", 10000).sleep(); // let things catch up
|
||||
wo.btNext().clickMouse();
|
||||
}
|
||||
|
@ -76,6 +76,8 @@
|
||||
<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 -->
|
||||
<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}/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"/>
|
||||
|
18
developers/README.txt
Executable file
18
developers/README.txt
Executable 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.
|
||||
|
||||
|
||||
|
||||
|
Binary file not shown.
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Braces_FOR_LOOP.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Braces_FOR_LOOP.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Braces_IF.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Braces_IF.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Braces_WHILE_LOOP.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Braces_WHILE_LOOP.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/EmptyStatements_IF.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/EmptyStatements_IF.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Imports_STAR.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Imports_STAR.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Javac_DEPRECATED.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Javac_DEPRECATED.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
@ -0,0 +1 @@
|
||||
enabled=true
|
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Javac_FALLTHROUGH.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Javac_FALLTHROUGH.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Javac_FINALLY.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Javac_FINALLY.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
1
developers/netbeans_ide_java_hint_settings/Javac_OVERRIDES.properties
Executable file
1
developers/netbeans_ide_java_hint_settings/Javac_OVERRIDES.properties
Executable file
@ -0,0 +1 @@
|
||||
enabled=true
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user