mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-06 21:00:22 +00:00
Merge branch 'develop' of github.com:sleuthkit/autopsy into develop
This commit is contained in:
commit
0179e86e78
1
.gitignore
vendored
1
.gitignore
vendored
@ -65,7 +65,6 @@ genfiles.properties
|
||||
!/Testing/nbproject/project.properties
|
||||
*~
|
||||
/netbeans-plat
|
||||
/docs/doxygen/doxygen_docs
|
||||
/docs/doxygen-user/user-docs
|
||||
/jdiff-javadocs/*
|
||||
/jdiff-logs/*
|
||||
|
56
BUILDING.txt
56
BUILDING.txt
@ -1,8 +1,8 @@
|
||||
Last Updated: Sept 17, 2014
|
||||
Last Updated: 27 April 2015
|
||||
|
||||
This file outlines what it takes to build Autopsy from source.
|
||||
|
||||
Note that it currently only works out of the box on Windows. We
|
||||
Note that it currently only works out-of-the-box on Windows. We
|
||||
are working on getting the process working under non-Windows systems.
|
||||
It generally works, but needs some custom mangling to find the
|
||||
correct C libraries.
|
||||
@ -11,7 +11,10 @@ correct C libraries.
|
||||
STEPS:
|
||||
1) Get Java Setup
|
||||
|
||||
1a) Download and install JDK version 1.8. For the current version of JavaFX that we use, you'll need 1.8.0_40 or greater. You can now use 32-bit or 64-bit, but special work is needed to get The Sleuth Kit to compile as 64-bit. So, 32-bit is easier.
|
||||
1a) Download and install JDK version 1.8. For the current version of JavaFX
|
||||
that we use, you'll need 1.8.0_40 or greater. You can now use 32-bit or 64-bit,
|
||||
but special work is needed to get The Sleuth Kit to compile as 64-bit. So,
|
||||
32-bit is easier, but if you intend to use PostgreSQL, choose 64-bit.
|
||||
|
||||
Autopsy has been used and tested with Oracle JavaSE and the included JavaFX support
|
||||
(http://www.oracle.com/technetwork/java/javase/downloads/index.html).
|
||||
@ -28,33 +31,25 @@ but it is a recommended IDE to use for development of Autopsy modules.
|
||||
need to set JRE_HOME_32 to the root 32-bit JRE directory and/or JRE_HOME_64
|
||||
to the root 64-bit JRE directory.
|
||||
|
||||
1e) (optional) For some Autopsy features to be functional, you need to add java executable to the system PATH.
|
||||
|
||||
1e) (optional) For some Autopsy features to be functional, you need to add the
|
||||
java executable to the system PATH.
|
||||
|
||||
|
||||
2) Get Sleuth Kit Setup
|
||||
2a) Download and build the release version of Libewf2 (20130119 or
|
||||
later). All you need is the dll file. Note that you will get a
|
||||
launching error if you use libewf 1.
|
||||
- http://sourceforge.net/projects/libewf/
|
||||
If you want to build the 64-bit version of The Sleuth Kit, download
|
||||
our 64-bit version of libewf:
|
||||
- https://github.com/sleuthkit/libewf_64bit
|
||||
|
||||
2b) Set LIBEWF_HOME environment variable to root directory of LIBEWF
|
||||
|
||||
2c) Download and build a Release version of Sleuth Kit (TSK) 4.0. You
|
||||
need to build the tsk_jni project. You can use a released version or
|
||||
download the latest from github:
|
||||
2a) Download and build a Release version of Sleuth Kit (TSK) 4.0. See
|
||||
win32\BUILDING.txt in the TSK package for more information. You need to
|
||||
build the tsk_jni project. Select the Release_PostgreSQL x64 target. You can
|
||||
use a released version or download the latest from github:
|
||||
- git://github.com/sleuthkit/sleuthkit.git
|
||||
|
||||
2d) Build the TSK JAR file by typing 'ant' in bindings/java in the
|
||||
TSK source code folder from a command line. You can also add the
|
||||
code to a NetBeans project and build it from there.
|
||||
2b) Build the TSK JAR file by typing 'ant PostgreSQL' in bindings/java in the
|
||||
TSK source code folder from a command line. Note it is case sensitive. You
|
||||
can also add the code to a NetBeans project and build it from there,
|
||||
selecting the PostgreSQL target.
|
||||
|
||||
2e) Set TSK_HOME environment variable to the root directory of TSK
|
||||
2c) Set TSK_HOME environment variable to the root directory of TSK
|
||||
|
||||
2f) On Non-Windows systems, you will need to do a 'make install'
|
||||
2d) On Non-Windows systems, you will need to do a 'make install'
|
||||
from the TSK root directory to install the libraries and such in
|
||||
the needed places (i.e. '/usr/local').
|
||||
|
||||
@ -85,12 +80,12 @@ and by submitting pull requests to the main Autopsy repository.
|
||||
5) Compile Autopsy
|
||||
5a) using Netbeans IDE:
|
||||
- Start NetBeans IDE and open the Autopsy project.
|
||||
- Choose to build the Autopsy project / module. It is the highest
|
||||
level project that will then cause the other modules to be compiled.
|
||||
- Choose to build the Autopsy project / module. It is the highest level project
|
||||
that will cause the other modules to be compiled.
|
||||
|
||||
5b) without Netbeans IDE (requires JDK and ant >= 1.7.1):
|
||||
- from root directory of Autopsy source execute:
|
||||
ant build
|
||||
ant
|
||||
(to build Autopsy)
|
||||
ant run
|
||||
(to run Autopsy)
|
||||
@ -102,13 +97,12 @@ the build process.
|
||||
|
||||
- The Sleuth Kit Java datamodel JAR file has native JNI libraries
|
||||
that are copied into it. These JNI libraries have dependencies on
|
||||
libewf and zlib. On non-Windows platforms, the JNI library also has
|
||||
a dependency on libtsk (on Windows, it is compiled into libtsk_jni).
|
||||
libewf, zlib, libpq, libintl-8, libeay32, and ssleay32 DLL files. On non-Windows
|
||||
platforms, the JNI library also has a dependency on libtsk (on Windows,
|
||||
it is compiled into libtsk_jni).
|
||||
|
||||
- NetBeans uses ant to build Autopsy. The build target copies the
|
||||
TSK datamodel JAR file into the project. If you want to use the
|
||||
debug version of the TSK dll, then there is a different ant target
|
||||
in the TSK datamodel to copy the debug versions of the dlls.
|
||||
TSK datamodel JAR file into the project.
|
||||
|
||||
- On a Windows system, the compile-time ant target copies the
|
||||
dependency libraries into the Autopsy code structure so that they can
|
||||
|
@ -24,6 +24,10 @@
|
||||
<property environment="env"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/dist/Tsk_DataModel.jar" tofile="${basedir}/release/modules/ext/Tsk_DataModel.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.8.11.jar" tofile="${basedir}/release/modules/ext/sqlite-jdbc-3.8.11.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/postgresql-9.4-1201-jdbc41.jar" tofile="${basedir}/release/modules/ext/postgresql-9.4-1201-jdbc41.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/mchange-commons-java-0.2.9.jar" tofile="${basedir}/release/modules/ext/mchange-commons-java-0.2.9.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/c3p0-0.9.5.jar" tofile="${basedir}/release/modules/ext/c3p0-0.9.5.jar"/>
|
||||
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.8.11.jar" tofile="${basedir}/release/modules/ext/sqlite-jdbc-3.8.11.jar"/>
|
||||
</target>
|
||||
|
||||
|
||||
|
@ -1,19 +1,21 @@
|
||||
file.reference.activemq-all-5.11.1.jar=release/modules/ext/activemq-all-5.11.1.jar
|
||||
file.reference.jdom-2.0.5-contrib.jar=release/modules/ext/jdom-2.0.5-contrib.jar
|
||||
file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
|
||||
file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone-2.7.0.jar
|
||||
file.reference.jython.jar-1=release/modules/ext/jython.jar
|
||||
file.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1.jar
|
||||
file.reference.postgresql-9.4-1201-jdbc41.jar=release/modules/ext/postgresql-9.4-1201-jdbc41.jar
|
||||
file.reference.opencv-248.jar=release/modules/ext/opencv-248.jar
|
||||
file.reference.Rejistry-1.0-SNAPSHOT.jar=release/modules/ext/Rejistry-1.0-SNAPSHOT.jar
|
||||
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
|
||||
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
|
||||
file.reference.sqlite-jdbc-3.8.11.jar=release/modules/ext/sqlite-jdbc-3.8.11.jar
|
||||
file.reference.StixLib.jar=release/modules/ext/StixLib.jar
|
||||
file.reference.tika-core-1.2.jar=release/modules/ext/tika-core-1.2.jar
|
||||
file.reference.tika-core-1.5.jar=release/modules/ext/tika-core-1.5.jar
|
||||
file.reference.Tsk_DataModel.jar=release/modules/ext/Tsk_DataModel.jar
|
||||
file.reference.xmpcore-5.1.2.jar=release/modules/ext/xmpcore-5.1.2.jar
|
||||
javac.source=1.8
|
||||
javac.compilerargs=-Xlint -Xlint:-serial
|
||||
javadoc.reference.metadata-extractor-2.8.1.jar=release/modules/ext/metadata-extractor-2.8.1-src.zip
|
||||
license.file=../LICENSE-2.0.txt
|
||||
nbm.homepage=http://www.sleuthkit.org/
|
||||
nbm.module.author=Brian Carrier
|
||||
|
@ -184,9 +184,11 @@
|
||||
<public-packages>
|
||||
<package>org.sleuthkit.autopsy.actions</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule.events</package>
|
||||
<package>org.sleuthkit.autopsy.casemodule.services</package>
|
||||
<package>org.sleuthkit.autopsy.contentviewers</package>
|
||||
<package>org.sleuthkit.autopsy.core</package>
|
||||
<package>org.sleuthkit.autopsy.core.events</package>
|
||||
<package>org.sleuthkit.autopsy.corecomponentinterfaces</package>
|
||||
<package>org.sleuthkit.autopsy.corecomponents</package>
|
||||
<package>org.sleuthkit.autopsy.coreutils</package>
|
||||
@ -203,14 +205,26 @@
|
||||
<package>org.sleuthkit.autopsy.report</package>
|
||||
<package>org.sleuthkit.datamodel</package>
|
||||
</public-packages>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/xmpcore-5.1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/xmpcore-5.1.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jdom-2.0.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jdom-2.0.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/postgresql-9.4-1201-jdbc41.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/postgresql-9.4-1201-jdbc41.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/mchange-commons-java-0.2.9.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/mchange-commons-java-0.2.9.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/c3p0-0.9.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/c3p0-0.9.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/xmpcore-5.1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/xmpcore-5.1.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/StixLib.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/StixLib.jar</binary-origin>
|
||||
@ -228,20 +242,32 @@
|
||||
<binary-origin>release/modules/ext/Rejistry-1.0-SNAPSHOT.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sevenzipjbinding.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
|
||||
<runtime-relative-path>ext/activemq-all-5.11.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/activemq-all-5.11.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/Rejistry-1.0-SNAPSHOT.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/Rejistry-1.0-SNAPSHOT.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jython-standalone-2.7.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jython-standalone-2.7.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sevenzipjbinding.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sevenzipjbinding.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/tika-core-1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/tika-core-1.2.jar</binary-origin>
|
||||
<runtime-relative-path>ext/tika-core-1.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/tika-core-1.5.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/metadata-extractor-2.8.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/metadata-extractor-2.8.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/metadata-extractor-2.8.1.jar</runtime-relative-path>
|
||||
|
BIN
Core/release/modules/ext/activemq-all-5.11.1.jar
Normal file
BIN
Core/release/modules/ext/activemq-all-5.11.1.jar
Normal file
Binary file not shown.
BIN
Core/release/modules/ext/metadata-extractor-2.8.1-src.zip
Executable file
BIN
Core/release/modules/ext/metadata-extractor-2.8.1-src.zip
Executable file
Binary file not shown.
Binary file not shown.
BIN
Core/release/modules/ext/tika-core-1.5.jar
Normal file
BIN
Core/release/modules/ext/tika-core-1.5.jar
Normal file
Binary file not shown.
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,7 +21,7 @@ package org.sleuthkit.autopsy.actions;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ -63,12 +63,15 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
|
||||
|
||||
@Override
|
||||
protected void addTag(TagName tagName, String comment) {
|
||||
Collection<? extends BlackboardArtifact> selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
|
||||
final Collection<? extends BlackboardArtifact> selectedArtifacts = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifact.class);
|
||||
|
||||
new Thread(() -> {
|
||||
for (BlackboardArtifact artifact : selectedArtifacts) {
|
||||
try {
|
||||
Case.getCurrentCase().getServices().getTagsManager().addBlackboardArtifactTag(artifact, tagName, comment);
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(AddBlackboardArtifactTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddBlackboardArtifactTagAction.unableToTag.msg",
|
||||
@ -76,7 +79,9 @@ public class AddBlackboardArtifactTagAction extends AddTagAction {
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddBlackboardArtifactTagAction.taggingErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-15 Basis Technology Corp.
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -22,6 +22,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ -41,6 +42,7 @@ public class AddContentTagAction extends AddTagAction {
|
||||
// This class is a singleton to support multi-selection of nodes, since
|
||||
// org.openide.nodes.NodeOp.findActions(Node[] nodes) will only pick up an Action if every
|
||||
// node in the array returns a reference to the same action object from Node.getActions(boolean).
|
||||
|
||||
private static AddContentTagAction instance;
|
||||
|
||||
public static synchronized AddContentTagAction getInstance() {
|
||||
@ -63,15 +65,18 @@ public class AddContentTagAction extends AddTagAction {
|
||||
|
||||
@Override
|
||||
protected void addTag(TagName tagName, String comment) {
|
||||
Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
|
||||
final Collection<? extends AbstractFile> selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class);
|
||||
|
||||
new Thread(() -> {
|
||||
for (AbstractFile file : selectedFiles) {
|
||||
try {
|
||||
// Handle the special cases of current (".") and parent ("..") directory entries.
|
||||
if (".".equals(file.getName())) {
|
||||
if (file.getName().equals(".")) {
|
||||
Content parentFile = file.getParent();
|
||||
if (parentFile instanceof AbstractFile) {
|
||||
file = (AbstractFile) parentFile;
|
||||
} else {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.unableToTag.msg",
|
||||
@ -79,55 +84,74 @@ public class AddContentTagAction extends AddTagAction {
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.cannotApplyTagErr"),
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
} else if ("..".equals(file.getName())) {
|
||||
} else if (file.getName().equals("..")) {
|
||||
Content parentFile = file.getParent();
|
||||
if (parentFile instanceof AbstractFile) {
|
||||
parentFile = parentFile.getParent();
|
||||
parentFile = (AbstractFile) ((AbstractFile) parentFile).getParent();
|
||||
if (parentFile instanceof AbstractFile) {
|
||||
file = (AbstractFile) parentFile;
|
||||
} else {
|
||||
final Content parentFileCopy = parentFile;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.unableToTag.msg",
|
||||
parentFile.getName()),
|
||||
parentFileCopy.getName()),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.cannotApplyTagErr"),
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
final Content parentFileCopy = parentFile;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.unableToTag.msg",
|
||||
parentFile.getName()),
|
||||
parentFileCopy.getName()),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.cannotApplyTagErr"),
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
});
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// check if the same tag is being added for the same abstract file.
|
||||
TagsManager tagsManager = Case.getCurrentCase().getServices().getTagsManager();
|
||||
List<ContentTag> contentTagList = tagsManager.getContentTagsByContent(file);
|
||||
boolean alreadyTaggedWithTagName = contentTagList.stream()
|
||||
.map(ContentTag::getName)
|
||||
.filter(tagName::equals)
|
||||
.findAny().isPresent();
|
||||
if (alreadyTaggedWithTagName) {
|
||||
continue; //skip this file, it already has a tag with this TagName.
|
||||
for (ContentTag contentTag : contentTagList) {
|
||||
if (contentTag.getName().getDisplayName().equals(tagName.getDisplayName())) {
|
||||
AbstractFile fileCopy = file;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.tagExists",
|
||||
fileCopy.getName(), tagName.getDisplayName()),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.cannotApplyTagErr"),
|
||||
JOptionPane.WARNING_MESSAGE);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
tagsManager.addContentTag(file, tagName, comment);
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error tagging result", ex); //NON-NLS
|
||||
AbstractFile fileCopy = file;
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"AddContentTagAction.unableToTag.msg2",
|
||||
file.getName()),
|
||||
fileCopy.getName()),
|
||||
NbBundle.getMessage(this.getClass(), "AddContentTagAction.taggingErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,12 @@ GetTagNameDialog.taggingErr=Tagging Error
|
||||
GetTagNameDialog.tagNameAlreadyDef.msg=A {0} tag name has already been defined.
|
||||
GetTagNameDialog.dupTagErr=Duplicate Tag Error
|
||||
OpenLogFolder.error1=Log File Not Found: {0}
|
||||
OpenLogFolder.CouldNotOpenLogFolder=Could not open log folder
|
||||
CTL_OpenLogFolder=Open Log Folder
|
||||
CTL_OpenOutputFolder=Open Output Folder
|
||||
OpenOutputFolder.error1=Output Folder Not Found: {0}
|
||||
OpenOutputFolder.noCaseOpen=No open case, therefore no current output folder available.
|
||||
OpenOutputFolder.CouldNotOpenOutputFolder=Could not open output folder
|
||||
ShowIngestProgressSnapshotAction.actionName.text=Get Ingest Progress Snapshot
|
||||
OpenPythonModulesFolderAction.actionName.text=Python Plugins
|
||||
OpenPythonModulesFolderAction.errorMsg.folderNotFound=Python plugins folder not found: {0}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,6 +23,7 @@ import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ -36,6 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public class DeleteBlackboardArtifactTagAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String MENU_TEXT = NbBundle.getMessage(DeleteBlackboardArtifactTagAction.class,
|
||||
"DeleteBlackboardArtifactTagAction.deleteTags");
|
||||
|
||||
@ -57,12 +59,14 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
Collection<? extends BlackboardArtifactTag> selectedTags = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactTag.class);
|
||||
final Collection<? extends BlackboardArtifactTag> selectedTags = Utilities.actionsGlobalContext().lookupAll(BlackboardArtifactTag.class);
|
||||
new Thread(() -> {
|
||||
for (BlackboardArtifactTag tag : selectedTags) {
|
||||
try {
|
||||
Case.getCurrentCase().getServices().getTagsManager().deleteBlackboardArtifactTag(tag);
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"DeleteBlackboardArtifactTagAction.unableToDelTag.msg",
|
||||
@ -70,7 +74,34 @@ public class DeleteBlackboardArtifactTagAction extends AbstractAction {
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"DeleteBlackboardArtifactTagAction.tagDelErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use actionPerformed() instead.
|
||||
*
|
||||
* @param event The event associated with the action.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
protected void doAction(ActionEvent event) {
|
||||
actionPerformed(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, does nothing. The TagManager methods to create, update or
|
||||
* delete tags now notify the case that there is a tag change. The case then
|
||||
* publishes an event that triggers a refresh of the tags sub-tree in the
|
||||
* tree view.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
protected void refreshDirectoryTree() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013 Basis Technology Corp.
|
||||
* Copyright 2013-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,6 +23,7 @@ import java.util.Collection;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.Utilities;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ -35,6 +36,7 @@ import org.sleuthkit.datamodel.TskCoreException;
|
||||
*/
|
||||
public class DeleteContentTagAction extends AbstractAction {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final String MENU_TEXT = NbBundle.getMessage(DeleteContentTagAction.class,
|
||||
"DeleteContentTagAction.deleteTags");
|
||||
|
||||
@ -56,19 +58,48 @@ public class DeleteContentTagAction extends AbstractAction {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Collection<? extends ContentTag> selectedTags = Utilities.actionsGlobalContext().lookupAll(ContentTag.class);
|
||||
final Collection<? extends ContentTag> selectedTags = Utilities.actionsGlobalContext().lookupAll(ContentTag.class);
|
||||
new Thread(() -> {
|
||||
for (ContentTag tag : selectedTags) {
|
||||
try {
|
||||
Case.getCurrentCase().getServices().getTagsManager().deleteContentTag(tag);
|
||||
} catch (TskCoreException ex) {
|
||||
Logger.getLogger(AddContentTagAction.class.getName()).log(Level.SEVERE, "Error deleting tag", ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"DeleteContentTagAction.unableToDelTag.msg",
|
||||
tag.getName()),
|
||||
NbBundle.getMessage(this.getClass(), "DeleteContentTagAction.tagDelErr"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
});
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, use actionPerformed() instead.
|
||||
*
|
||||
* @param event The event associated with the action.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
protected void doAction(ActionEvent event) {
|
||||
actionPerformed(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deprecated, does nothing. The TagManager methods to create, update or
|
||||
* delete tags now notify the case that there is a tag change. The case then
|
||||
* publishes an event that triggers a refresh of the tags sub-tree in the
|
||||
* tree view.
|
||||
*
|
||||
* @deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
protected void refreshDirectoryTree() {
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -23,15 +23,16 @@ import java.awt.event.ActionListener;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
import org.openide.awt.ActionRegistration;
|
||||
import org.openide.modules.Places;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Action in menu to open the folder containing the log files
|
||||
@ -42,6 +43,8 @@ import org.sleuthkit.autopsy.casemodule.Case;
|
||||
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenLogFolderAction", category = "Help")
|
||||
public final class OpenLogFolderAction implements ActionListener {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(OpenLogFolderAction.class.getName());
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
try {
|
||||
@ -61,7 +64,8 @@ public final class OpenLogFolderAction implements ActionListener {
|
||||
Desktop.getDesktop().open(logDir);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenLogFolder.CouldNotOpenLogFolder"), ex); //NON-NLS
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.actions;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.Desktop;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.awt.ActionID;
|
||||
import org.openide.awt.ActionReference;
|
||||
import org.openide.awt.ActionRegistration;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Action in menu to open the folder containing the output files
|
||||
*/
|
||||
@ActionRegistration(
|
||||
displayName = "#CTL_OpenOutputFolder", iconInMenu = true)
|
||||
@ActionReference(path = "Menu/Help", position = 1850)
|
||||
@ActionID(id = "org.sleuthkit.autopsy.actions.OpenOutputFolderAction", category = "Help")
|
||||
public final class OpenOutputFolderAction implements ActionListener {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(OpenOutputFolderAction.class.getName());
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
try {
|
||||
File outputDir;
|
||||
if (Case.isCaseOpen()) {
|
||||
outputDir = new File(Case.getCurrentCase().getOutputDirectory());
|
||||
if (outputDir.exists() == false) {
|
||||
NotifyDescriptor d
|
||||
= new NotifyDescriptor.Message(NbBundle.getMessage(this.getClass(),
|
||||
"OpenOutputFolder.error1", outputDir.getAbsolutePath()),
|
||||
NotifyDescriptor.ERROR_MESSAGE);
|
||||
DialogDisplayer.getDefault().notify(d);
|
||||
} else {
|
||||
Desktop.getDesktop().open(outputDir);
|
||||
}
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.noCaseOpen"));
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, NbBundle.getMessage(this.getClass(), "OpenOutputFolder.CouldNotOpenOutputFolder"), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
@ -20,12 +20,10 @@ package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.File;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
@ -33,7 +31,8 @@ import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.openide.windows.WindowManager;
|
||||
import java.awt.Cursor;
|
||||
|
||||
/**
|
||||
* The "Add Image" wizard panel1 handling the logic of selecting image file(s)
|
||||
@ -70,6 +69,7 @@ class AddImageWizardChooseDataSourcePanel implements WizardDescriptor.Panel<Wiza
|
||||
@Override
|
||||
public AddImageWizardChooseDataSourceVisual getComponent() {
|
||||
if (component == null) {
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
component = new AddImageWizardChooseDataSourceVisual(this);
|
||||
}
|
||||
component.addPropertyChangeListener(this);
|
||||
|
@ -84,7 +84,13 @@ final class AddImageWizardChooseDataSourceVisual extends JPanel {
|
||||
// make a list of core DSPs
|
||||
// ensure that the core DSPs are at the top and in a fixed order
|
||||
coreDSPTypes.add(ImageDSProcessor.getType());
|
||||
// Local disk processing is not allowed for multi-user cases
|
||||
if (Case.getCurrentCase().getCaseType() != Case.CaseType.MULTI_USER_CASE) {
|
||||
coreDSPTypes.add(LocalDiskDSProcessor.getType());
|
||||
} else {
|
||||
// remove LocalDiskDSProcessor from list of DSPs
|
||||
datasourceProcessorsMap.remove(LocalDiskDSProcessor.getType());
|
||||
}
|
||||
coreDSPTypes.add(LocalFilesDSProcessor.getType());
|
||||
|
||||
for (String dspType : coreDSPTypes) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -25,13 +25,13 @@ import java.awt.Window;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessorCallback;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
@ -47,7 +47,7 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
*/
|
||||
class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDescriptor> {
|
||||
|
||||
private IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||
private final IngestJobSettingsPanel ingestJobSettingsPanel;
|
||||
|
||||
/**
|
||||
* The visual component that displays this panel. If you need to access the
|
||||
@ -220,13 +220,14 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
* DataSourceProcessor
|
||||
*/
|
||||
private void startDataSourceProcessing(WizardDescriptor settings) {
|
||||
final UUID dataSourceId = UUID.randomUUID();
|
||||
|
||||
// Add a cleanup task to interrupt the background process if the
|
||||
// wizard exits while the background process is running.
|
||||
cleanupTask = addImageAction.new CleanupTask() {
|
||||
@Override
|
||||
void cleanup() throws Exception {
|
||||
cancelDataSourceProcessing();
|
||||
cancelDataSourceProcessing(dataSourceId);
|
||||
}
|
||||
};
|
||||
|
||||
@ -235,10 +236,13 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
// get the selected DSProcessor
|
||||
dsProcessor = dataSourcePanel.getComponent().getCurrentDSProcessor();
|
||||
|
||||
new Thread(() -> {
|
||||
Case.getCurrentCase().notifyAddingDataSource(dataSourceId);
|
||||
}).start();
|
||||
DataSourceProcessorCallback cbObj = new DataSourceProcessorCallback() {
|
||||
@Override
|
||||
public void doneEDT(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
|
||||
dataSourceProcessorDone(result, errList, contents);
|
||||
dataSourceProcessorDone(dataSourceId, result, errList, contents);
|
||||
}
|
||||
|
||||
};
|
||||
@ -253,7 +257,10 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
/*
|
||||
* Cancels the data source processing - in case the users presses 'Cancel'
|
||||
*/
|
||||
private void cancelDataSourceProcessing() {
|
||||
private void cancelDataSourceProcessing(UUID dataSourceId) {
|
||||
new Thread(() -> {
|
||||
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
|
||||
}).start();
|
||||
dsProcessor.cancel();
|
||||
}
|
||||
|
||||
@ -261,8 +268,7 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
* Callback for the data source processor. Invoked by the DSP on the EDT
|
||||
* thread, when it finishes processing the data source.
|
||||
*/
|
||||
private void dataSourceProcessorDone(DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
|
||||
|
||||
private void dataSourceProcessorDone(UUID dataSourceId, DataSourceProcessorCallback.DataSourceProcessorResult result, List<String> errList, List<Content> contents) {
|
||||
// disable the cleanup task
|
||||
cleanupTask.disable();
|
||||
|
||||
@ -301,10 +307,13 @@ class AddImageWizardIngestConfigPanel implements WizardDescriptor.Panel<WizardDe
|
||||
newContents.addAll(contents);
|
||||
|
||||
//notify the UI of the new content added to the case
|
||||
new Thread(() -> {
|
||||
if (!newContents.isEmpty()) {
|
||||
|
||||
Case.getCurrentCase().notifyNewDataSource(newContents.get(0));
|
||||
Case.getCurrentCase().notifyDataSourceAdded(newContents.get(0), dataSourceId);
|
||||
} else {
|
||||
Case.getCurrentCase().notifyFailedAddingDataSource(dataSourceId);
|
||||
}
|
||||
}).start();
|
||||
|
||||
// Start ingest if we can
|
||||
progressPanel.setStateStarted();
|
||||
|
@ -107,13 +107,13 @@ AddImageWizardIngestConfigVisual.getName.text=Configure Ingest Modules
|
||||
AddImageWizardIterator.stepXofN=Step {0} of {1}
|
||||
AddLocalFilesTask.localFileAdd.progress.text=Adding\: {0}/{1}
|
||||
Case.getCurCase.exception.noneOpen=Cannot get the current case; there is no case open\!
|
||||
Case.moduleErr=Module Error
|
||||
Case.changeCase.errListenToCaseUpdates.msg=A module caused an error listening to Case updates. See log to determine which module. Some data could be incomplete.
|
||||
Case.create.exception.msg=Error creating a case\: {0} in dir {1}
|
||||
Case.databaseConnectionInfo.error.msg=Error accessing case database connection info
|
||||
Case.open.exception.blankCase.msg=Case name is blank.
|
||||
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.checkFile.msg=Check that you selected the correct case file (usually with {0} extension)
|
||||
Case.open.exception.multiUserCaseNotEnabled=Cannot open a multi-user case if multi-user cases are not enabled. See Tools, Options, Multi-user.
|
||||
Case.open.exception.gen.msg=Error opening the case
|
||||
Case.checkImgExist.confDlg.doesntExist.msg={0} has detected that one of the images associated with \n\
|
||||
this case are missing. Would you like to search for them now?\n\
|
||||
@ -135,7 +135,11 @@ Case.createCaseDir.exception.existCantRW=Cannot create case dir, already exists
|
||||
Case.createCaseDir.exception.cantCreate=Cannot create case dir\: {0}
|
||||
Case.createCaseDir.exception.cantCreateCaseDir=Could not create case directory\: {0}
|
||||
Case.createCaseDir.exception.cantCreateModDir=Could not create modules output directory\: {0}
|
||||
Case.createCaseDir.exception.cantCreateReportsDir=Could not create reports output directory\: {0}
|
||||
Case.createCaseDir.exception.gen=Could not create case directory\: {0}
|
||||
Case.CollaborationSetup.FailNotify.ErrMsg=Failed to connect to any other nodes that may be collaborating on this case.
|
||||
Case.CollaborationSetup.FailNotify.Title=Connection Failure
|
||||
Case.GetCaseTypeGivenPath.Failure=Unable to get case type
|
||||
CaseDeleteAction.closeConfMsg.text=Are you sure want to close and delete this case? \n\
|
||||
Case Name\: {0}\n\
|
||||
Case Directory\: {1}
|
||||
@ -145,10 +149,11 @@ Close the folder and file and try again or you can delete the case manually.
|
||||
CaseDeleteAction.msgDlg.fileInUse.title=Error\: Folder In Use
|
||||
CaseDeleteAction.msgDlg.caseDelete.msg=Case {0} has been deleted.
|
||||
CaseOpenAction.autFilter.title={0} Case File ( {1})
|
||||
CaseOpenAction.msgDlg.fileNotExist.msg=Error\: File does not exist.
|
||||
CaseOpenAction.msgDlg.fileNotExist.title=Error
|
||||
CaseOpenAction.msgDlg.cantOpenCase.msg=Error\: could not open the case in folder {0}\: {1}
|
||||
CaseOpenAction.msgDlg.cantOpenCase.title=Error
|
||||
CaseOpenAction.msgDlg.cantOpenCase.title=Error Opening Case
|
||||
CaseCreateAction.msgDlg.cantCreateCase.msg=Cannot create case
|
||||
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
|
||||
@ -183,13 +188,18 @@ MissingImageDialog.allDesc.text=All Supported Types
|
||||
MissingImageDialog.display.title=Search for Missing Image
|
||||
MissingImageDialog.confDlg.noFileSel.msg=No image file has been selected, are you sure you\nwould like to exit without finding the image.
|
||||
MissingImageDialog.confDlg.noFileSel.title=Missing Image
|
||||
MissingImageDialog.ErrorSettingImage=Error setting image path. Please try again.
|
||||
NewCaseVisualPanel1.getName.text=Case Info
|
||||
NewCaseVisualPanel1.caseDirBrowse.selectButton.text=Select
|
||||
NewCaseVisualPanel1.badCredentials.text=Bad multi-user settings (see Tools, Options, Multi-user) or services are down.
|
||||
NewCaseVisualPanel1.MultiUserDisabled.text=Multi-user cases not enabled. See Tools, Options, Multi-user.
|
||||
NewCaseVisualPanel2.getName.text=Additional Information
|
||||
NewCaseWizardAction.closeCurCase.confMsg.msg=Do you want to save and close this case and proceed with the new case creation?
|
||||
NewCaseWizardAction.closeCurCase.confMsg.title=Warning\: Closing the Current Case
|
||||
NewCaseWizardAction.newCase.windowTitle.text=New Case Information
|
||||
NewCaseWizardAction.getName.text=New Case Wizard
|
||||
NewCaseWizardAction.databaseProblem1.text=Cannot open database. Cancelling case creation.
|
||||
NewCaseWizardAction.databaseProblem2.text=Error
|
||||
NewCaseWizardPanel1.validate.errMsg.invalidSymbols=The Case Name cannot contain any of the following symbols\: \\ / \: * ? " < > |
|
||||
NewCaseWizardPanel1.validate.errMsg.dirExists=Case directory ''{0}'' already exists.
|
||||
NewCaseWizardPanel1.validate.confMsg.createDir.msg=The base directory "{0}" does not exist. \n\n\
|
||||
@ -221,5 +231,33 @@ Detail\: \n\
|
||||
Cannot open a non-Autopsy config file (at {1}).
|
||||
XMLCaseManagement.open.msgDlg.notAutCase.title=Error
|
||||
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=Cancel
|
||||
ImageFilePanel.errorLabel.text=Error Label
|
||||
DataSourceOnCDriveError.text=Warning: Path to multi-user data source is on \"C:\" drive
|
||||
NewCaseVisualPanel1.CaseFolderOnCDriveError.text=Warning: Path to multi-user case folder is on \"C:\" drive
|
||||
LocalFilesPanel.errorLabel.text=Error Label
|
||||
CollaborationMonitor.addingDataSourceStatus.msg={0} adding data source
|
||||
CollaborationMonitor.analyzingDataSourceStatus.msg={0} analyzing {1}
|
||||
MissingImageDialog.lbWarning.text=
|
||||
MissingImageDialog.lbWarning.toolTipText=
|
||||
SingleUserCaseImporter.AlreadyMultiUser=Case is already multi-user!
|
||||
SingleUserCaseImporter.BadCaseSourceFolder=Case source folder does not exist!
|
||||
SingleUserCaseImporter.BadImageSourceFolder=Image source folder does not exist!
|
||||
SingleUserCaseImporter.BadDatabaseFileName=Database file does not exist!
|
||||
SingleUserCaseImporter.NonUniqueOutputFolder=Output folder not unique. Skipping
|
||||
SingleUserCaseImporter.NonUniqueDatabaseName=Database name not unique. Skipping.
|
||||
SingleUserCaseImporter.PotentiallyNonUniqueDatabaseName=Unclear if database name unique. Moving ahead.
|
||||
SingleUserCaseImporter.ImportedAsMultiUser=\nThis case was imported as a multi-user collaborative case on
|
||||
SingleUserCaseImporter.UnableToCopySourceImages=Unable to copy source images
|
||||
SingleUserCaseImporter.DeletingCase=Deleting original case folder
|
||||
SingleUserCaseImporter.CanNotOpenDatabase=Unable to open database
|
||||
SingleUserCaseImporter.WillImport=Will import:
|
||||
SingleUserCaseImporter.WillNotImport=Will not import:
|
||||
SingleUserCaseImporter.None=None
|
||||
SingleUserCaseImporter.ContinueWithImport=Continue with import?
|
||||
SingleUserCaseImporter.Cancelled=Cancelled
|
||||
NewCaseVisualPanel1.caseParentDirWarningLabel.text=Case directory warning label
|
||||
NewCaseVisualPanel1.multiUserCaseRadioButton.text=Multi-user
|
||||
NewCaseVisualPanel1.singleUserCaseRadioButton.text=Single-user
|
||||
NewCaseVisualPanel1.multiUserSettingsWarningLabel.text=Multi-user settings warning label
|
||||
Case.deleteReports.deleteFromDiskException.log.msg=Unable to delete the report from the disk.
|
||||
Case.deleteReports.deleteFromDiskException.msg=Unable to delete the report {0} from the disk.\nYou may manually delete it from {1}
|
||||
|
@ -102,8 +102,6 @@ AddImageWizardIngestConfigVisual.getName.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30
|
||||
AddImageWizardIterator.stepXofN=\u30b9\u30c6\u30c3\u30d7{0}\uff0f{1}
|
||||
AddLocalFilesTask.localFileAdd.progress.text=\u8ffd\u52a0\u4e2d\uff1a{0}/{1}
|
||||
Case.getCurCase.exception.noneOpen=\u73fe\u5728\u306e\u30b1\u30fc\u30b9\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\uff1b\u958b\u3044\u3066\u3044\u308b\u30b1\u30fc\u30b9\u304c\u3042\u308a\u307e\u305b\u3093\uff01
|
||||
Case.moduleErr=\u30e2\u30b8\u30e5\u30fc\u30eb\u30a8\u30e9\u30fc
|
||||
Case.changeCase.errListenToCaseUpdates.msg=\u30b1\u30fc\u30b9\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3092\u78ba\u8a8d\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u8d77\u3053\u3057\u307e\u3057\u305f\u3002\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304b\u30ed\u30b0\u3067\u78ba\u8a8d\u3057\u3066\u4e0b\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u304b\u3082\u3057\u308c\u307e\u305b\u3093\u3002
|
||||
Case.create.exception.msg=\u30b1\u30fc\u30b9\u4f5c\u6210\u4e2d\u306b\u30a8\u30e9\u30fc\u304c\u767a\u751f\u3057\u307e\u3057\u305f\uff1a\u30c7\u30a3\u30ec\u30af\u30c8\u30ea{1}\u306e{0}
|
||||
Case.open.exception.blankCase.msg=\u30b1\u30fc\u30b9\u540d\u304c\u7a7a\u767d\u3067\u3059\u3002
|
||||
Case.open.msgDlg.updated.msg=\u30b1\u30fc\u30b9\u30c7\u30fc\u30bf\u30d9\u30fc\u30b9\u30b9\u30ad\u30fc\u30de\u3092\u30a2\u30c3\u30d7\u30c7\u30fc\u30c8\u3057\u307e\u3057\u305f\u3002\n\
|
||||
@ -217,3 +215,6 @@ XMLCaseManagement.open.msgDlg.notAutCase.title=\u30a8\u30e9\u30fc
|
||||
ImageFilePanel.noFatOrphansCheckbox.text=FAT\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u30aa\u30fc\u30d5\u30a1\u30f3\u30d5\u30a1\u30a4\u30eb\u306f\u7121\u8996
|
||||
LocalDiskPanel.noFatOrphansCheckbox.text=FAT\u30d5\u30a1\u30a4\u30eb\u30b7\u30b9\u30c6\u30e0\u306e\u30aa\u30fc\u30d5\u30a1\u30f3\u30d5\u30a1\u30a4\u30eb\u306f\u7121\u8996
|
||||
AddImageWizardIngestConfigPanel.CANCEL_BUTTON.text=\u30ad\u30e3\u30f3\u30bb\u30eb
|
||||
ImageFilePanel.errorLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb
|
||||
LocalFilesPanel.errorLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb
|
||||
NewCaseVisualPanel1.caseParentDirWarningLabel.text=\u30a8\u30e9\u30fc\u30e9\u30d9\u30eb
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -19,15 +19,11 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.SwingWorker;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
@ -37,7 +33,7 @@ import org.openide.util.actions.Presenter;
|
||||
* The action to close the current Case. This class should be disabled on
|
||||
* creation and it will be enabled on new case creation or case opened.
|
||||
*/
|
||||
final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
|
||||
public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar {
|
||||
|
||||
JButton toolbarButton = new JButton();
|
||||
|
||||
@ -49,13 +45,7 @@ final class CaseCloseAction extends CallableSystemAction implements Presenter.To
|
||||
putValue(Action.NAME, NbBundle.getMessage(CaseCloseAction.class, "CTL_CaseCloseAct")); // put the action Name
|
||||
|
||||
// set action of the toolbar button
|
||||
toolbarButton.addActionListener(new ActionListener() {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
CaseCloseAction.this.actionPerformed(e);
|
||||
}
|
||||
});
|
||||
toolbarButton.addActionListener(CaseCloseAction.this::actionPerformed);
|
||||
|
||||
this.setEnabled(false);
|
||||
}
|
||||
@ -71,23 +61,24 @@ final class CaseCloseAction extends CallableSystemAction implements Presenter.To
|
||||
return;
|
||||
}
|
||||
|
||||
Case result = Case.getCurrentCase();
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
if (!MessageNotifyUtil.Message.confirm("Are you sure you want to close current case?")) {
|
||||
return;
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
try {
|
||||
Case result = Case.getCurrentCase();
|
||||
result.closeCase();
|
||||
} catch (CaseActionException | IllegalStateException unused) {
|
||||
// Already logged.
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
result.closeCase();
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
protected void done() {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
} catch (Exception ex) {
|
||||
Logger.getLogger(CaseCloseAction.class.getName()).log(Level.WARNING, "Error closing case.", ex); //NON-NLS
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
|
136
Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java
Normal file
136
Core/src/org/sleuthkit/autopsy/casemodule/CaseMetadata.java
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 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;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Provides access to case metadata.
|
||||
*/
|
||||
public final class CaseMetadata {
|
||||
|
||||
/**
|
||||
* Exception thrown by the CaseMetadata class when there is a problem
|
||||
* accessing the metadata for a case.
|
||||
*/
|
||||
public final static class CaseMetadataException extends Exception {
|
||||
|
||||
private CaseMetadataException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
private CaseMetadataException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
private final Case.CaseType caseType;
|
||||
private final String caseName;
|
||||
private final String caseNumber;
|
||||
private final String examiner;
|
||||
private final String caseDirectory;
|
||||
private final String caseDatabaseName;
|
||||
|
||||
/**
|
||||
* Constructs an object that provides access to case metadata.
|
||||
*
|
||||
* @param metadataFilePath
|
||||
*/
|
||||
public CaseMetadata(Path metadataFilePath) throws CaseMetadataException {
|
||||
try {
|
||||
// NOTE: This class will eventually replace XMLCaseManagement.
|
||||
// This constructor should parse all of the metadata. In the future,
|
||||
// case metadata may be moved into the case database.
|
||||
XMLCaseManagement metadata = new XMLCaseManagement();
|
||||
metadata.open(metadataFilePath.toString());
|
||||
caseType = metadata.getCaseType();
|
||||
caseName = metadata.getCaseName();
|
||||
if (caseName.isEmpty()) {
|
||||
throw new CaseMetadataException("Case name missing");
|
||||
}
|
||||
caseNumber = metadata.getCaseNumber();
|
||||
examiner = metadata.getCaseExaminer();
|
||||
caseDirectory = metadata.getCaseDirectory();
|
||||
if (caseDirectory.isEmpty()) {
|
||||
throw new CaseMetadataException("Case directory missing");
|
||||
}
|
||||
caseDatabaseName = metadata.getDatabaseName();
|
||||
if (Case.CaseType.MULTI_USER_CASE == caseType && caseDatabaseName.isEmpty()) {
|
||||
throw new CaseMetadataException("Case database name missing");
|
||||
}
|
||||
} catch (CaseActionException ex) {
|
||||
throw new CaseMetadataException(ex.getLocalizedMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case type.
|
||||
*
|
||||
* @return The case type.
|
||||
*/
|
||||
public Case.CaseType getCaseType() {
|
||||
return this.caseType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case name.
|
||||
*
|
||||
* @return The case name.
|
||||
*/
|
||||
public String getCaseName() {
|
||||
return caseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case number.
|
||||
*
|
||||
* @return The case number, may be empty.
|
||||
*/
|
||||
public String getCaseNumber() {
|
||||
return caseNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the examiner.
|
||||
*
|
||||
* @return The examiner, may be empty.
|
||||
*/
|
||||
public String getExaminer() {
|
||||
return examiner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case directory.
|
||||
*
|
||||
* @return The case directory.
|
||||
*/
|
||||
public String getCaseDirectory() {
|
||||
return caseDirectory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case database name.
|
||||
*
|
||||
* @return The case database name, will be empty for a single-user case.
|
||||
*/
|
||||
public String getCaseDatabaseName() {
|
||||
return caseDatabaseName;
|
||||
}
|
||||
|
||||
}
|
@ -19,6 +19,9 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.SystemAction;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
|
||||
@ -28,7 +31,7 @@ import org.openide.util.lookup.ServiceProvider;
|
||||
* @author jantonius
|
||||
*/
|
||||
@ServiceProvider(service = CaseNewActionInterface.class)
|
||||
public final class CaseNewAction implements CaseNewActionInterface {
|
||||
public final class CaseNewAction extends CallableSystemAction implements CaseNewActionInterface {
|
||||
|
||||
private NewCaseWizardAction wizard = SystemAction.get(NewCaseWizardAction.class);
|
||||
|
||||
@ -41,4 +44,18 @@ public final class CaseNewAction implements CaseNewActionInterface {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
wizard.performAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performAction() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return NbBundle.getMessage(CaseNewAction.class, "CTL_CaseNewAction");
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return HelpCtx.DEFAULT_HELP;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,97 +18,87 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.openide.windows.WindowManager;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.Version;
|
||||
|
||||
/**
|
||||
* The action to open a existing case. This class is always enabled.
|
||||
* An action that opens an existing case.
|
||||
*/
|
||||
@ServiceProvider(service = CaseOpenAction.class)
|
||||
public final class CaseOpenAction implements ActionListener {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(CaseOpenAction.class.getName());
|
||||
private static final String PROP_BASECASE = "LBL_BaseCase_PATH"; //NON-NLS
|
||||
private final JFileChooser fc = new JFileChooser();
|
||||
private FileFilter autFilter;
|
||||
private final JFileChooser fileChooser = new JFileChooser();
|
||||
private final FileFilter caseMetadataFileFilter;
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
* Constructs an action that opens an existing case.
|
||||
*/
|
||||
public CaseOpenAction() {
|
||||
autFilter = new FileNameExtensionFilter(
|
||||
NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(),
|
||||
Case.CASE_DOT_EXTENSION),
|
||||
Case.CASE_EXTENSION);
|
||||
fc.setDragEnabled(false);
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
fc.setFileFilter(autFilter);
|
||||
try {
|
||||
if (ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE) != null) {
|
||||
fc.setCurrentDirectory(new File(ModuleSettings.getConfigSetting("Case", PROP_BASECASE))); //NON-NLS
|
||||
}
|
||||
} catch (Exception e) {
|
||||
caseMetadataFileFilter = new FileNameExtensionFilter(NbBundle.getMessage(CaseOpenAction.class, "CaseOpenAction.autFilter.title", Version.getName(), Case.CASE_DOT_EXTENSION), Case.CASE_EXTENSION);
|
||||
fileChooser.setDragEnabled(false);
|
||||
fileChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
fileChooser.setFileFilter(caseMetadataFileFilter);
|
||||
if (null != ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE)) {
|
||||
fileChooser.setCurrentDirectory(new File(ModuleSettings.getConfigSetting("Case", PROP_BASECASE))); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pop-up the File Chooser to open the existing case (.aut file)
|
||||
* Pops up a file chooser to allow the user to select a case meta data file
|
||||
* (.aut file) and attempts to open the case described by the file.
|
||||
*
|
||||
* @param e the action event
|
||||
* @param e The action event.
|
||||
*/
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
int retval = fc.showOpenDialog((Component) e.getSource());
|
||||
|
||||
/**
|
||||
* Pop up a file chooser to allow the user to select a case meta data
|
||||
* file (.aut file)
|
||||
*/
|
||||
int retval = fileChooser.showOpenDialog(WindowManager.getDefault().getMainWindow());
|
||||
if (retval == JFileChooser.APPROVE_OPTION) {
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
String dirPath = fc.getSelectedFile().getParent();
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator)));
|
||||
// check if the file exists
|
||||
if (!new File(path).exists()) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseOpenAction.msgDlg.fileNotExist.msg"),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseOpenAction.msgDlg.fileNotExist.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
this.actionPerformed(e); // show the dialog box again
|
||||
} else {
|
||||
// try to close Startup window if there's one
|
||||
/**
|
||||
* This is a bit of a hack, but close the startup window, if it was
|
||||
* the source of the action invocation.
|
||||
*/
|
||||
try {
|
||||
StartupWindowProvider.getInstance().close();
|
||||
} catch (Exception ex) {
|
||||
// no need to show the error message to the user.
|
||||
logger.log(Level.WARNING, "Error closing startup window.", ex); //NON-NLS
|
||||
} catch (Exception unused) {
|
||||
}
|
||||
try {
|
||||
Case.open(path); // open the case
|
||||
} catch (CaseActionException ex) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseOpenAction.msgDlg.cantOpenCase.msg", path,
|
||||
ex.getMessage()),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseOpenAction.msgDlg.cantOpenCase.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
logger.log(Level.WARNING, "Error opening case in folder " + path, ex); //NON-NLS
|
||||
|
||||
/**
|
||||
* Try to open the caswe associated with the case meta data file the
|
||||
* user selected.
|
||||
*/
|
||||
final String path = fileChooser.getSelectedFile().getPath();
|
||||
String dirPath = fileChooser.getSelectedFile().getParent();
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, dirPath.substring(0, dirPath.lastIndexOf(File.separator)));
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case.open(path);
|
||||
} catch (CaseActionException ex) {
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null, ex.getMessage(), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), JOptionPane.ERROR_MESSAGE);
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,12 @@
|
||||
|
||||
<xs:element name="Examiner" type="String" nillable="true"/>
|
||||
|
||||
<xs:element name="CaseType" type="String" nillable="false"/>
|
||||
|
||||
<xs:element name="DatabaseName" type="String" nillable="false"/>
|
||||
|
||||
<xs:element name="TextIndexName" type="String" nillable="true"/>
|
||||
|
||||
<xs:attribute name="Relative" type="xs:boolean"/>
|
||||
|
||||
<xs:element name="CreatedDate" >
|
||||
@ -92,6 +98,11 @@
|
||||
<xs:element ref="LogFolder"/>
|
||||
<xs:element ref="TempFolder"/>
|
||||
<xs:element ref="CacheFolder"/>
|
||||
<xs:sequence minOccurs="0" maxOccurs="1">
|
||||
<xs:element ref="CaseType"/>
|
||||
<xs:element ref="DatabaseName"/>
|
||||
<xs:element ref="TextIndexName"/>
|
||||
</xs:sequence>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
@ -0,0 +1,601 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 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;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.io.Serializable;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import org.netbeans.api.progress.ProgressHandle;
|
||||
import org.netbeans.api.progress.ProgressHandleFactory;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.AddingDataSourceFailedEvent;
|
||||
import org.sleuthkit.autopsy.casemodule.events.DataSourceAddedEvent;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.NetworkUtils;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventException;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisCompletedEvent;
|
||||
import org.sleuthkit.autopsy.ingest.events.DataSourceAnalysisStartedEvent;
|
||||
|
||||
/**
|
||||
* A collaboration monitor listens to local events and translates them into
|
||||
* collaboration tasks that are broadcast to collaborating nodes and informs the
|
||||
* user of collaboration tasks on other nodes using progress bars.
|
||||
*/
|
||||
final class CollaborationMonitor {
|
||||
|
||||
private static final String EVENT_CHANNEL_NAME = "%s-Collaboration-Monitor-Events";
|
||||
private static final String COLLABORATION_MONITOR_EVENT = "COLLABORATION_MONITOR_EVENT";
|
||||
private static final Set<String> CASE_EVENTS_OF_INTEREST = new HashSet<>(Arrays.asList(new String[]{Case.Events.ADDING_DATA_SOURCE.toString(), Case.Events.DATA_SOURCE_ADDED.toString(), Case.Events.ADDING_DATA_SOURCE_FAILED.toString()}));
|
||||
private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 2;
|
||||
private static final String PERIODIC_TASK_THREAD_NAME = "collab-monitor-periodic-tasks-%d";
|
||||
private static final long HEARTBEAT_INTERVAL_MINUTES = 1;
|
||||
private static final long MAX_MISSED_HEARTBEATS = 5;
|
||||
private static final long STALE_TASKS_DETECTION_INTERVAL_MINUTES = 2;
|
||||
private static final long EXECUTOR_TERMINATION_WAIT_SECS = 30;
|
||||
private static final Logger logger = Logger.getLogger(CollaborationMonitor.class.getName());
|
||||
private final String hostName;
|
||||
private final LocalTasksManager localTasksManager;
|
||||
private final RemoteTasksManager remoteTasksManager;
|
||||
private final AutopsyEventPublisher eventPublisher;
|
||||
private final ScheduledThreadPoolExecutor periodicTasksExecutor;
|
||||
|
||||
/**
|
||||
* Constructs a collaboration monitor that listens to local events and
|
||||
* translates them into collaboration tasks that are broadcast to
|
||||
* collaborating nodes, informs the user of collaboration tasks on other
|
||||
* nodes using progress bars, and monitors the health of key collaboration
|
||||
* services.
|
||||
*/
|
||||
CollaborationMonitor() throws CollaborationMonitorException {
|
||||
/**
|
||||
* Get the local host name so it can be used to identify the source of
|
||||
* collaboration tasks broadcast by this node.
|
||||
*/
|
||||
hostName = NetworkUtils.getLocalHostName();
|
||||
|
||||
/**
|
||||
* Create an event publisher that will be used to communicate with
|
||||
* collaboration monitors on other nodes working on the case.
|
||||
*/
|
||||
eventPublisher = new AutopsyEventPublisher();
|
||||
try {
|
||||
Case openedCase = Case.getCurrentCase();
|
||||
String channelPrefix = openedCase.getTextIndexName();
|
||||
eventPublisher.openRemoteEventChannel(String.format(EVENT_CHANNEL_NAME, channelPrefix));
|
||||
} catch (AutopsyEventException ex) {
|
||||
throw new CollaborationMonitorException("Failed to initialize", ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a remote tasks manager to track and display the progress of
|
||||
* remote tasks.
|
||||
*/
|
||||
remoteTasksManager = new RemoteTasksManager();
|
||||
eventPublisher.addSubscriber(COLLABORATION_MONITOR_EVENT, remoteTasksManager);
|
||||
|
||||
/**
|
||||
* Create a local tasks manager to track and broadcast local tasks.
|
||||
*/
|
||||
localTasksManager = new LocalTasksManager();
|
||||
IngestManager.getInstance().addIngestJobEventListener(localTasksManager);
|
||||
Case.addEventSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager);
|
||||
|
||||
/**
|
||||
* Start periodic tasks that:
|
||||
*
|
||||
* 1. Send heartbeats to collaboration monitors on other nodes.<br>
|
||||
* 2. Check for stale remote tasks.<br>
|
||||
*/
|
||||
periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build());
|
||||
periodicTasksExecutor.scheduleAtFixedRate(new HeartbeatTask(), HEARTBEAT_INTERVAL_MINUTES, HEARTBEAT_INTERVAL_MINUTES, TimeUnit.MINUTES);
|
||||
periodicTasksExecutor.scheduleAtFixedRate(new StaleTaskDetectionTask(), STALE_TASKS_DETECTION_INTERVAL_MINUTES, STALE_TASKS_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down this collaboration monitor.
|
||||
*/
|
||||
void shutdown() {
|
||||
if (null != periodicTasksExecutor) {
|
||||
periodicTasksExecutor.shutdownNow();
|
||||
try {
|
||||
while (!periodicTasksExecutor.awaitTermination(EXECUTOR_TERMINATION_WAIT_SECS, TimeUnit.SECONDS)) {
|
||||
logger.log(Level.WARNING, "Waited at least {0} seconds for periodic tasks executor to shut down, continuing to wait", EXECUTOR_TERMINATION_WAIT_SECS); //NON-NLS
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
logger.log(Level.SEVERE, "Unexpected interrupt while stopping periodic tasks executor", ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
Case.removeEventSubscriber(CASE_EVENTS_OF_INTEREST, localTasksManager);
|
||||
IngestManager.getInstance().removeIngestJobEventListener(localTasksManager);
|
||||
|
||||
if (null != eventPublisher) {
|
||||
eventPublisher.removeSubscriber(COLLABORATION_MONITOR_EVENT, remoteTasksManager);
|
||||
eventPublisher.closeRemoteEventChannel();
|
||||
}
|
||||
|
||||
remoteTasksManager.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* The local tasks manager listens to local events and translates them into
|
||||
* tasks it broadcasts to collaborating nodes. Note that all access to the
|
||||
* task collections is synchronized since they may be accessed by both the
|
||||
* threads publishing property change events and by the heartbeat task
|
||||
* thread.
|
||||
*/
|
||||
private final class LocalTasksManager implements PropertyChangeListener {
|
||||
|
||||
private long nextTaskId;
|
||||
private final Map<Integer, Task> uuidsToAddDataSourceTasks;
|
||||
private final Map<Long, Task> jobIdsTodataSourceAnalysisTasks;
|
||||
|
||||
/**
|
||||
* Constructs a local tasks manager that listens to local events and
|
||||
* translates them into tasks that can be broadcast to collaborating
|
||||
* nodes.
|
||||
*/
|
||||
LocalTasksManager() {
|
||||
nextTaskId = 0;
|
||||
uuidsToAddDataSourceTasks = new HashMap<>();
|
||||
jobIdsTodataSourceAnalysisTasks = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates events into updates of the collection of local tasks this
|
||||
* node is broadcasting to other nodes.
|
||||
*
|
||||
* @param event A PropertyChangeEvent.
|
||||
*/
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
if (AutopsyEvent.SourceType.LOCAL == ((AutopsyEvent) event).getSourceType()) {
|
||||
String eventName = event.getPropertyName();
|
||||
if (eventName.equals(Case.Events.ADDING_DATA_SOURCE.toString())) {
|
||||
addDataSourceAddTask((AddingDataSourceEvent) event);
|
||||
} else if (eventName.equals(Case.Events.ADDING_DATA_SOURCE_FAILED.toString())) {
|
||||
removeDataSourceAddTask(((AddingDataSourceFailedEvent) event).getDataSourceId());
|
||||
} else if (eventName.equals(Case.Events.DATA_SOURCE_ADDED.toString())) {
|
||||
removeDataSourceAddTask(((DataSourceAddedEvent) event).getDataSourceId());
|
||||
} else if (eventName.equals(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_STARTED.toString())) {
|
||||
addDataSourceAnalysisTask((DataSourceAnalysisStartedEvent) event);
|
||||
} else if (eventName.equals(IngestManager.IngestJobEvent.DATA_SOURCE_ANALYSIS_COMPLETED.toString())) {
|
||||
removeDataSourceAnalysisTask((DataSourceAnalysisCompletedEvent) event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an adding data source task to the collection of local tasks and
|
||||
* publishes the updated collection to any collaborating nodes.
|
||||
*
|
||||
* @param event An adding data source event.
|
||||
*/
|
||||
synchronized void addDataSourceAddTask(AddingDataSourceEvent event) {
|
||||
String status = NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.addingDataSourceStatus.msg", hostName);
|
||||
uuidsToAddDataSourceTasks.put(event.getDataSourceId().hashCode(), new Task(++nextTaskId, status));
|
||||
eventPublisher.publishRemotely(new CollaborationEvent(hostName, getCurrentTasks()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an adding data source task from the collection of local tasks
|
||||
* and publishes the updated collection to any collaborating nodes.
|
||||
*
|
||||
* @param dataSourceId A data source id to pair a data source added or
|
||||
* adding data source failed event with an adding
|
||||
* data source event.
|
||||
*/
|
||||
synchronized void removeDataSourceAddTask(UUID dataSourceId) {
|
||||
uuidsToAddDataSourceTasks.remove(dataSourceId.hashCode());
|
||||
eventPublisher.publishRemotely(new CollaborationEvent(hostName, getCurrentTasks()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a data source analysis task to the collection of local tasks and
|
||||
* publishes the updated collection to any collaborating nodes.
|
||||
*
|
||||
* @param event A data source analysis started event.
|
||||
*/
|
||||
synchronized void addDataSourceAnalysisTask(DataSourceAnalysisStartedEvent event) {
|
||||
String status = NbBundle.getMessage(CollaborationMonitor.class, "CollaborationMonitor.analyzingDataSourceStatus.msg", hostName, event.getDataSource().getName());
|
||||
jobIdsTodataSourceAnalysisTasks.put(event.getDataSourceIngestJobId(), new Task(++nextTaskId, status));
|
||||
eventPublisher.publishRemotely(new CollaborationEvent(hostName, getCurrentTasks()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a data source analysis task from the collection of local
|
||||
* tasks and publishes the updated collection to any collaborating
|
||||
* nodes.
|
||||
*
|
||||
* @param event A data source analysis completed event.
|
||||
*/
|
||||
synchronized void removeDataSourceAnalysisTask(DataSourceAnalysisCompletedEvent event) {
|
||||
jobIdsTodataSourceAnalysisTasks.remove(event.getDataSourceIngestJobId());
|
||||
eventPublisher.publishRemotely(new CollaborationEvent(hostName, getCurrentTasks()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current local tasks.
|
||||
*
|
||||
* @return A mapping of task IDs to tasks, may be empty.
|
||||
*/
|
||||
synchronized Map<Long, Task> getCurrentTasks() {
|
||||
Map<Long, Task> currentTasks = new HashMap<>();
|
||||
uuidsToAddDataSourceTasks.values().stream().forEach((task) -> {
|
||||
currentTasks.put(task.getId(), task);
|
||||
});
|
||||
jobIdsTodataSourceAnalysisTasks.values().stream().forEach((task) -> {
|
||||
currentTasks.put(task.getId(), task);
|
||||
});
|
||||
return currentTasks;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for collaboration event messages broadcast by collaboration
|
||||
* monitors on other nodes and translates them into remote tasks represented
|
||||
* locally using progress bars. Note that all access to the remote tasks is
|
||||
* synchronized since it may be accessed by both the threads publishing
|
||||
* property change events and by the thread running periodic checks for
|
||||
* "stale" tasks.
|
||||
*/
|
||||
private final class RemoteTasksManager implements PropertyChangeListener {
|
||||
|
||||
private final Map<String, RemoteTasks> hostsToTasks;
|
||||
|
||||
/**
|
||||
* Constructs an object that listens for collaboration event messages
|
||||
* broadcast by collaboration monitors on other nodes and translates
|
||||
* them into remote tasks represented locally using progress bars.
|
||||
*/
|
||||
RemoteTasksManager() {
|
||||
hostsToTasks = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the remote tasks in response to a collaboration event
|
||||
* received from another node.
|
||||
*
|
||||
* @param event The collaboration event.
|
||||
*/
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
if (event.getPropertyName().equals(COLLABORATION_MONITOR_EVENT)) {
|
||||
updateTasks((CollaborationEvent) event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress bars for all remote tasks.
|
||||
*/
|
||||
synchronized void shutdown() {
|
||||
finishAllTasks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the remote tasks to reflect a collaboration event received
|
||||
* from another node.
|
||||
*
|
||||
* @param event The collaboration event.
|
||||
*/
|
||||
synchronized void updateTasks(CollaborationEvent event) {
|
||||
RemoteTasks tasksForHost = hostsToTasks.get(event.getHostName());
|
||||
if (null != tasksForHost) {
|
||||
tasksForHost.update(event);
|
||||
} else {
|
||||
hostsToTasks.put(event.getHostName(), new RemoteTasks(event));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress bars any remote tasks that have gone stale,
|
||||
* i.e., tasks for which updates have ceased, presumably because the
|
||||
* collaborating node has gone down or there is a network issue.
|
||||
*/
|
||||
synchronized void finishStaleTasks() {
|
||||
for (Iterator<Map.Entry<String, RemoteTasks>> it = hostsToTasks.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<String, RemoteTasks> entry = it.next();
|
||||
RemoteTasks tasksForHost = entry.getValue();
|
||||
if (tasksForHost.isStale()) {
|
||||
tasksForHost.finishAllTasks();
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the progress bars for all remote tasks.
|
||||
*/
|
||||
synchronized void finishAllTasks() {
|
||||
for (Iterator<Map.Entry<String, RemoteTasks>> it = hostsToTasks.entrySet().iterator(); it.hasNext();) {
|
||||
Map.Entry<String, RemoteTasks> entry = it.next();
|
||||
RemoteTasks tasksForHost = entry.getValue();
|
||||
tasksForHost.finishAllTasks();
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of progress bars for tasks on a collaborating node.
|
||||
*/
|
||||
private final class RemoteTasks {
|
||||
|
||||
private final long MAX_MINUTES_WITHOUT_UPDATE = HEARTBEAT_INTERVAL_MINUTES * MAX_MISSED_HEARTBEATS;
|
||||
private Instant lastUpdateTime;
|
||||
private Map<Long, ProgressHandle> taskIdsToProgressBars;
|
||||
|
||||
/**
|
||||
* Construct a set of progress bars to represent remote tasks for a
|
||||
* particular host.
|
||||
*
|
||||
* @param event A collaboration event.
|
||||
*/
|
||||
RemoteTasks(CollaborationEvent event) {
|
||||
/**
|
||||
* Set the initial value of the last update time stamp.
|
||||
*/
|
||||
lastUpdateTime = Instant.now();
|
||||
|
||||
taskIdsToProgressBars = new HashMap<>();
|
||||
event.getCurrentTasks().values().stream().forEach((task) -> {
|
||||
ProgressHandle progress = ProgressHandleFactory.createHandle(event.getHostName());
|
||||
progress.start();
|
||||
progress.progress(task.getStatus());
|
||||
taskIdsToProgressBars.put(task.getId(), progress);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this remote tasks collection.
|
||||
*
|
||||
* @param event A collaboration event from the collaborating node
|
||||
* associated with these tasks.
|
||||
*/
|
||||
void update(CollaborationEvent event) {
|
||||
/**
|
||||
* Update the last update timestamp.
|
||||
*/
|
||||
lastUpdateTime = Instant.now();
|
||||
|
||||
/**
|
||||
* Create or update the progress bars for the current tasks of
|
||||
* the node that published the event.
|
||||
*/
|
||||
Map<Long, Task> remoteTasks = event.getCurrentTasks();
|
||||
remoteTasks.values().stream().forEach((task) -> {
|
||||
ProgressHandle progress = taskIdsToProgressBars.get(task.getId());
|
||||
if (null != progress) {
|
||||
/**
|
||||
* Update the existing progress bar.
|
||||
*/
|
||||
progress.progress(task.getStatus());
|
||||
} else {
|
||||
/**
|
||||
* A new task, create a progress bar.
|
||||
*/
|
||||
progress = ProgressHandleFactory.createHandle(event.getHostName());
|
||||
progress.start();
|
||||
progress.progress(task.getStatus());
|
||||
taskIdsToProgressBars.put(task.getId(), progress);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* If a task is no longer in the task list from the remote node,
|
||||
* it is finished. Remove the progress bars for finished tasks.
|
||||
*/
|
||||
for (Iterator<Map.Entry<Long, ProgressHandle>> iterator = taskIdsToProgressBars.entrySet().iterator(); iterator.hasNext();) {
|
||||
Map.Entry<Long, ProgressHandle> entry = iterator.next();
|
||||
if (!remoteTasks.containsKey(entry.getKey())) {
|
||||
ProgressHandle progress = entry.getValue();
|
||||
progress.finish();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unconditionally finishes the entire set or remote tasks. To be
|
||||
* used when a host drops off unexpectedly.
|
||||
*/
|
||||
void finishAllTasks() {
|
||||
taskIdsToProgressBars.values().stream().forEach((progress) -> {
|
||||
progress.finish();
|
||||
});
|
||||
taskIdsToProgressBars.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not the time since the last update of this
|
||||
* remote tasks collection is greater than the maximum acceptable
|
||||
* interval between updates.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean isStale() {
|
||||
return Duration.between(lastUpdateTime, Instant.now()).toMinutes() >= MAX_MINUTES_WITHOUT_UPDATE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A Runnable task that periodically publishes the local tasks in progress
|
||||
* on this node, providing a heartbeat message for collaboration monitors on
|
||||
* other nodes. The current local tasks are included in the heartbeat
|
||||
* message so that nodes that have just joined the event channel know what
|
||||
* this node is doing, even if they join after the current tasks are begun.
|
||||
*/
|
||||
private final class HeartbeatTask implements Runnable {
|
||||
|
||||
/**
|
||||
* Publish a heartbeat message.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
eventPublisher.publishRemotely(new CollaborationEvent(hostName, localTasksManager.getCurrentTasks()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Runnable task that periodically deals with any remote tasks that have
|
||||
* gone stale, i.e., tasks for which updates have ceased, presumably because
|
||||
* the collaborating node has gone down or there is a network issue.
|
||||
*/
|
||||
private final class StaleTaskDetectionTask implements Runnable {
|
||||
|
||||
/**
|
||||
* Check for stale remote tasks and clean them up, if found.
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
remoteTasksManager.finishStaleTasks();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An Autopsy event to be sent in event messages to the collaboration
|
||||
* monitors on other Autopsy nodes.
|
||||
*/
|
||||
private final static class CollaborationEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final String hostName;
|
||||
private final Map<Long, Task> currentTasks;
|
||||
|
||||
/**
|
||||
* Constructs an Autopsy event to be sent in event messages to the
|
||||
* collaboration monitors on other Autopsy nodes.
|
||||
*
|
||||
* @param hostName The name of the host sending the event.
|
||||
* @param currentTasks The tasks in progress for this Autopsy node.
|
||||
*/
|
||||
CollaborationEvent(String hostName, Map<Long, Task> currentTasks) {
|
||||
super(COLLABORATION_MONITOR_EVENT, null, null);
|
||||
this.hostName = hostName;
|
||||
this.currentTasks = currentTasks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the host name of the Autopsy node that published this event.
|
||||
*
|
||||
* @return The host name.
|
||||
*/
|
||||
String getHostName() {
|
||||
return hostName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current tasks for the Autopsy node that published this
|
||||
* event.
|
||||
*
|
||||
* @return A mapping of task IDs to current tasks
|
||||
*/
|
||||
Map<Long, Task> getCurrentTasks() {
|
||||
return currentTasks;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A representation of a task in progress on this Autopsy node.
|
||||
*/
|
||||
private final static class Task implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final long id;
|
||||
private final String status;
|
||||
|
||||
/**
|
||||
* Constructs a representation of a task in progress on this Autopsy
|
||||
* node.
|
||||
*
|
||||
* @param id
|
||||
* @param status
|
||||
*/
|
||||
Task(long id, String status) {
|
||||
this.id = id;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets ID of this task.
|
||||
*
|
||||
* @return A task id, unique to this task for this case and this Autopsy
|
||||
* node.
|
||||
*/
|
||||
long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the status of the task at the time this object was constructed.
|
||||
*
|
||||
* @return A task status string.
|
||||
*/
|
||||
String getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom exception class for the collaboration monitor.
|
||||
*/
|
||||
final static class CollaborationMonitorException extends Exception {
|
||||
|
||||
/**
|
||||
* Constructs and instance of the custom exception class for the
|
||||
* collaboration monitor.
|
||||
*
|
||||
* @param message Exception message.
|
||||
*/
|
||||
CollaborationMonitorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and instance of the custom exception class for the
|
||||
* collaboration monitor.
|
||||
*
|
||||
* @param message Exception message.
|
||||
* @param throwable Exception cause.
|
||||
*/
|
||||
CollaborationMonitorException(String message, Throwable throwable) {
|
||||
super(message, throwable);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,16 +18,18 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Dialog;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.KeyStroke;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
@ -42,7 +44,6 @@ public class CueBannerPanel extends javax.swing.JPanel {
|
||||
|
||||
// for error handling
|
||||
private static JPanel caller = new JPanel();
|
||||
private String className = this.getClass().toString();
|
||||
|
||||
public CueBannerPanel() {
|
||||
initComponents();
|
||||
@ -209,6 +210,10 @@ public class CueBannerPanel extends javax.swing.JPanel {
|
||||
|
||||
// set the location of the popUp Window on the center of the screen
|
||||
recentCasesWindow.setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||
recentCasesWindow.setLocationRelativeTo(this);
|
||||
recentCasesWindow.getRootPane().registerKeyboardAction(e -> {
|
||||
recentCasesWindow.dispose();
|
||||
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_IN_FOCUSED_WINDOW);
|
||||
|
||||
OpenRecentCasePanel welcomeWindow = OpenRecentCasePanel.getInstance();
|
||||
|
||||
|
@ -43,6 +43,7 @@
|
||||
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="errorLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="20" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
@ -57,7 +58,9 @@
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="pathTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="3" max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="timeZoneLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="timeZoneComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
@ -66,7 +69,7 @@
|
||||
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="13" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -131,5 +134,15 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="errorLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="ImageFilePanel.errorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -37,6 +37,7 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
|
||||
/**
|
||||
* ImageTypePanel for adding an image file such as .img, .E0x, .00x, etc.
|
||||
@ -65,6 +66,8 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
fc.setMultiSelectionEnabled(false);
|
||||
|
||||
errorLabel.setVisible(false);
|
||||
|
||||
boolean firstFilter = true;
|
||||
for (FileFilter filter : fileChooserFilters) {
|
||||
if (firstFilter) { // set the first on the list as the default selection
|
||||
@ -115,6 +118,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
timeZoneComboBox = new javax.swing.JComboBox<String>();
|
||||
noFatOrphansCheckbox = new javax.swing.JCheckBox();
|
||||
descLabel = new javax.swing.JLabel();
|
||||
errorLabel = new javax.swing.JLabel();
|
||||
|
||||
setMinimumSize(new java.awt.Dimension(0, 65));
|
||||
setPreferredSize(new java.awt.Dimension(403, 65));
|
||||
@ -139,6 +143,9 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(descLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.descLabel.text")); // NOI18N
|
||||
|
||||
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(ImageFilePanel.class, "ImageFilePanel.errorLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -158,7 +165,8 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(21, 21, 21)
|
||||
.addComponent(descLabel)))
|
||||
.addComponent(descLabel))
|
||||
.addComponent(errorLabel))
|
||||
.addGap(0, 20, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
@ -169,7 +177,9 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(browseButton)
|
||||
.addComponent(pathTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(18, 18, 18)
|
||||
.addGap(3, 3, 3)
|
||||
.addComponent(errorLabel)
|
||||
.addGap(1, 1, 1)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(timeZoneLabel)
|
||||
.addComponent(timeZoneComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
@ -177,7 +187,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(descLabel)
|
||||
.addContainerGap(13, Short.MAX_VALUE))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -208,6 +218,7 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton browseButton;
|
||||
private javax.swing.JLabel descLabel;
|
||||
private javax.swing.JLabel errorLabel;
|
||||
private javax.swing.JCheckBox noFatOrphansCheckbox;
|
||||
private javax.swing.JLabel pathLabel;
|
||||
private javax.swing.JTextField pathTextField;
|
||||
@ -252,11 +263,15 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
* @return true if a proper image has been selected, false otherwise
|
||||
*/
|
||||
public boolean validatePanel() {
|
||||
errorLabel.setVisible(false);
|
||||
String path = getContentPaths();
|
||||
if (path == null || path.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// display warning if there is one (but don't disable "next" button)
|
||||
warnIfPathIsInvalid(path);
|
||||
|
||||
boolean isExist = Case.pathExists(path);
|
||||
boolean isPhysicalDrive = Case.isPhysicalDrive(path);
|
||||
boolean isPartition = Case.isPartition(path);
|
||||
@ -264,6 +279,19 @@ public class ImageFilePanel extends JPanel implements DocumentListener {
|
||||
return (isExist || isPhysicalDrive || isPartition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates path to selected data source and displays warning if it is
|
||||
* invalid.
|
||||
*
|
||||
* @param path Absolute path to the selected data source
|
||||
*/
|
||||
private void warnIfPathIsInvalid(String path) {
|
||||
if (!PathValidator.isValid(path, Case.getCurrentCase().getCaseType())) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(NbBundle.getMessage(this.getClass(), "DataSourceOnCDriveError.text"));
|
||||
}
|
||||
}
|
||||
|
||||
public void storeSettings() {
|
||||
String imagePathName = getContentPaths();
|
||||
if (null != imagePathName) {
|
||||
|
@ -0,0 +1,6 @@
|
||||
package org.sleuthkit.autopsy.casemodule;
|
||||
|
||||
public interface ImportDoneCallback {
|
||||
|
||||
void importDoneCallback(boolean result, String resultString);
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 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;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
|
||||
/**
|
||||
* This class enables capturing errors and batching them for reporting on a
|
||||
* no-more-than-x number of seconds basis. When created, you specify the minimum
|
||||
* time between user notifications. When the time between notifications has
|
||||
* expired, the next error encountered will cause a report to be shown to the
|
||||
* user.
|
||||
*/
|
||||
class IntervalErrorReportData {
|
||||
|
||||
private final Case currentCase;
|
||||
private long newProblems;
|
||||
private long totalProblems;
|
||||
private long lastReportedDate;
|
||||
private final int milliSecondsBetweenReports;
|
||||
private final String message;
|
||||
|
||||
/**
|
||||
* Create a new IntervalErrorReprotData instance and subscribe for TSK error
|
||||
* notifications for the current case.
|
||||
*
|
||||
* @param currentCase Case for which TSK errors should be tracked
|
||||
* and displayed.
|
||||
* @param secondsBetweenReports Minimum number of seconds between reports.
|
||||
* It will not warn more frequently than this.
|
||||
* @param message The message that will be shown when warning
|
||||
* the user
|
||||
*/
|
||||
IntervalErrorReportData(Case currentCase, int secondsBetweenReports, String message) {
|
||||
this.newProblems = 0;
|
||||
this.totalProblems = 0;
|
||||
this.lastReportedDate = 0; // arm the first warning by choosing zero
|
||||
this.milliSecondsBetweenReports = secondsBetweenReports * 1000; // convert to milliseconds
|
||||
this.message = message;
|
||||
this.currentCase = currentCase;
|
||||
this.currentCase.getSleuthkitCase().addErrorObserver(this.currentCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-subscribe from TSK error notifications for current case.
|
||||
*/
|
||||
void shutdown() {
|
||||
this.currentCase.getSleuthkitCase().removeErrorObserver(this.currentCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this to add problems to the class. When the time threshold is met
|
||||
* (or if this is the first problem encountered), a warning will be shown to
|
||||
* the user.
|
||||
*
|
||||
* @param context The context in which the error occurred.
|
||||
* @param errorMessage A description of the error that occurred.
|
||||
*/
|
||||
void addProblems(String context, String errorMessage) {
|
||||
this.newProblems += 1;
|
||||
this.totalProblems += newProblems;
|
||||
|
||||
long currentTimeStamp = System.currentTimeMillis();
|
||||
if ((currentTimeStamp - lastReportedDate) > milliSecondsBetweenReports) {
|
||||
this.lastReportedDate = currentTimeStamp;
|
||||
MessageNotifyUtil.Notify.error(message, context + ", " + errorMessage + " "
|
||||
+ this.newProblems + " "
|
||||
+ NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.NewIssues")
|
||||
+ " " + this.totalProblems + " "
|
||||
+ NbBundle.getMessage(IntervalErrorReportData.class, "IntervalErrorReport.TotalIssues")
|
||||
+ ".");
|
||||
this.newProblems = 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -61,7 +61,7 @@
|
||||
<Component id="noFatOrphansCheckbox" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="descLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="21" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
|
@ -93,9 +93,9 @@ final class LocalDiskPanel extends JPanel {
|
||||
diskComboBox.setModel(model);
|
||||
diskComboBox.setRenderer(model);
|
||||
|
||||
errorLabel.setVisible(false);
|
||||
errorLabel.setText("");
|
||||
diskComboBox.setEnabled(false);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,7 +167,7 @@ final class LocalDiskPanel extends JPanel {
|
||||
.addComponent(noFatOrphansCheckbox)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(descLabel)
|
||||
.addContainerGap(21, Short.MAX_VALUE))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
|
@ -60,6 +60,10 @@
|
||||
</Group>
|
||||
<EmptySpace min="-2" pref="2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
@ -67,15 +71,16 @@
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="infoLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="5" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Component id="jScrollPane2" min="-2" pref="82" max="-2" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="selectButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="17" max="32767" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="clearButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jScrollPane2" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="errorLabel" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -136,5 +141,15 @@
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="errorLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="LocalFilesPanel.errorLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -21,6 +21,8 @@ package org.sleuthkit.autopsy.casemodule;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import javax.swing.JFileChooser;
|
||||
@ -30,7 +32,9 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponentinterfaces.DataSourceProcessor;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
|
||||
/**
|
||||
* Add input wizard subpanel for adding local files / dirs to the case
|
||||
@ -61,8 +65,8 @@ class LocalFilesPanel extends JPanel {
|
||||
|
||||
private void customInit() {
|
||||
localFileChooser.setMultiSelectionEnabled(true);
|
||||
errorLabel.setVisible(false);
|
||||
selectedPaths.setText("");
|
||||
|
||||
}
|
||||
|
||||
//@Override
|
||||
@ -93,9 +97,35 @@ class LocalFilesPanel extends JPanel {
|
||||
|
||||
//@Override
|
||||
public boolean validatePanel() {
|
||||
|
||||
// display warning if there is one (but don't disable "next" button)
|
||||
warnIfPathIsInvalid(getContentPaths());
|
||||
|
||||
return enableNext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates path to selected data source and displays warning if it is
|
||||
* invalid.
|
||||
*
|
||||
* @param path Absolute path to the selected data source
|
||||
*/
|
||||
private void warnIfPathIsInvalid(String path) {
|
||||
errorLabel.setVisible(false);
|
||||
|
||||
// Path variable for "Local files" module is a coma separated string containg multiple paths
|
||||
List<String> pathsList = Arrays.asList(path.split(","));
|
||||
CaseType currentCaseType = Case.getCurrentCase().getCaseType();
|
||||
|
||||
for (String currentPath : pathsList) {
|
||||
if (!PathValidator.isValid(currentPath, currentCaseType)) {
|
||||
errorLabel.setVisible(true);
|
||||
errorLabel.setText(NbBundle.getMessage(this.getClass(), "DataSourceOnCDriveError.text"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void select() {
|
||||
reset();
|
||||
@ -106,8 +136,7 @@ class LocalFilesPanel extends JPanel {
|
||||
currentFiles.clear();
|
||||
selectedPaths.setText("");
|
||||
enableNext = false;
|
||||
|
||||
//pcs.firePropertyChange(AddImageWizardChooseDataSourceVisual.EVENT.UPDATE_UI.toString(), false, true);
|
||||
errorLabel.setVisible(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -150,6 +179,7 @@ class LocalFilesPanel extends JPanel {
|
||||
clearButton = new javax.swing.JButton();
|
||||
jScrollPane2 = new javax.swing.JScrollPane();
|
||||
selectedPaths = new javax.swing.JTextArea();
|
||||
errorLabel = new javax.swing.JLabel();
|
||||
|
||||
localFileChooser.setApproveButtonText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonText")); // NOI18N
|
||||
localFileChooser.setApproveButtonToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.localFileChooser.approveButtonToolTipText")); // NOI18N
|
||||
@ -185,6 +215,9 @@ class LocalFilesPanel extends JPanel {
|
||||
selectedPaths.setToolTipText(org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.selectedPaths.toolTipText")); // NOI18N
|
||||
jScrollPane2.setViewportView(selectedPaths);
|
||||
|
||||
errorLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(errorLabel, org.openide.util.NbBundle.getMessage(LocalFilesPanel.class, "LocalFilesPanel.errorLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -199,19 +232,23 @@ class LocalFilesPanel extends JPanel {
|
||||
.addComponent(selectButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(clearButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGap(2, 2, 2))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(errorLabel)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(infoLabel)
|
||||
.addGap(5, 5, 5)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(selectButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 17, Short.MAX_VALUE)
|
||||
.addComponent(clearButton))
|
||||
.addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
|
||||
.addGap(0, 0, 0))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(clearButton)))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(errorLabel))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -256,6 +293,7 @@ class LocalFilesPanel extends JPanel {
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton clearButton;
|
||||
private javax.swing.JLabel errorLabel;
|
||||
private javax.swing.JLabel infoLabel;
|
||||
private javax.swing.JScrollPane jScrollPane1;
|
||||
private javax.swing.JScrollPane jScrollPane2;
|
||||
|
@ -112,12 +112,17 @@
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="lbWarning" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="pathNameTextField" min="-2" pref="285" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="83" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
@ -127,7 +132,9 @@
|
||||
<Component id="pathNameTextField" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="browseButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="62" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="lbWarning" pref="19" max="32767" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -153,6 +160,22 @@
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="browseButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbWarning">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="f4" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MissingImageDialog.lbWarning.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="MissingImageDialog.lbWarning.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JLabel" name="titleLabel">
|
||||
|
@ -137,6 +137,7 @@ class MissingImageDialog extends javax.swing.JDialog {
|
||||
containerPanel = new javax.swing.JPanel();
|
||||
pathNameTextField = new javax.swing.JTextField();
|
||||
browseButton = new javax.swing.JButton();
|
||||
lbWarning = new javax.swing.JLabel();
|
||||
titleLabel = new javax.swing.JLabel();
|
||||
titleSeparator = new javax.swing.JSeparator();
|
||||
|
||||
@ -191,16 +192,24 @@ class MissingImageDialog extends javax.swing.JDialog {
|
||||
}
|
||||
});
|
||||
|
||||
lbWarning.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
|
||||
lbWarning.setForeground(new java.awt.Color(244, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbWarning, org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.lbWarning.text")); // NOI18N
|
||||
lbWarning.setToolTipText(org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.lbWarning.toolTipText")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout containerPanelLayout = new javax.swing.GroupLayout(containerPanel);
|
||||
containerPanel.setLayout(containerPanelLayout);
|
||||
containerPanelLayout.setHorizontalGroup(
|
||||
containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(containerPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(lbWarning, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addGroup(containerPanelLayout.createSequentialGroup()
|
||||
.addComponent(pathNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 285, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(browseButton)
|
||||
.addContainerGap(83, Short.MAX_VALUE))
|
||||
.addContainerGap(83, Short.MAX_VALUE))))
|
||||
);
|
||||
containerPanelLayout.setVerticalGroup(
|
||||
containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -209,12 +218,13 @@ class MissingImageDialog extends javax.swing.JDialog {
|
||||
.addGroup(containerPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(pathNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(browseButton))
|
||||
.addContainerGap(62, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(lbWarning, javax.swing.GroupLayout.DEFAULT_SIZE, 19, Short.MAX_VALUE)
|
||||
.addGap(18, 18, 18))
|
||||
);
|
||||
|
||||
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, 12));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle
|
||||
.getMessage(MissingImageDialog.class, "MissingImageDialog.titleLabel.text")); // NOI18N
|
||||
titleLabel.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(titleLabel, org.openide.util.NbBundle.getMessage(MissingImageDialog.class, "MissingImageDialog.titleLabel.text")); // NOI18N
|
||||
|
||||
titleSeparator.setForeground(new java.awt.Color(102, 102, 102));
|
||||
|
||||
@ -254,10 +264,11 @@ class MissingImageDialog extends javax.swing.JDialog {
|
||||
String newPath = pathNameTextField.getText();
|
||||
//TODO handle local files
|
||||
db.setImagePaths(obj_id, Arrays.asList(new String[]{newPath}));
|
||||
this.dispose();
|
||||
} catch (TskCoreException ex) {
|
||||
lbWarning.setText(NbBundle.getMessage(this.getClass(), "MissingImageDialog.ErrorSettingImage"));
|
||||
logger.log(Level.WARNING, "Error setting image paths", ex); //NON-NLS
|
||||
}
|
||||
this.dispose();
|
||||
}//GEN-LAST:event_selectButtonActionPerformed
|
||||
|
||||
private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
|
||||
@ -273,7 +284,7 @@ class MissingImageDialog extends javax.swing.JDialog {
|
||||
private void browseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_browseButtonActionPerformed
|
||||
|
||||
String oldText = pathNameTextField.getText();
|
||||
|
||||
lbWarning.setText("");
|
||||
// set the current directory of the FileChooser if the ImagePath Field is valid
|
||||
File currentDir = new File(oldText);
|
||||
if (currentDir.exists()) {
|
||||
@ -294,6 +305,7 @@ class MissingImageDialog extends javax.swing.JDialog {
|
||||
private javax.swing.JPanel buttonPanel;
|
||||
private javax.swing.JButton cancelButton;
|
||||
private javax.swing.JPanel containerPanel;
|
||||
private javax.swing.JLabel lbWarning;
|
||||
private javax.swing.JTextField pathNameTextField;
|
||||
private javax.swing.JButton selectButton;
|
||||
private javax.swing.JLabel titleLabel;
|
||||
|
@ -1,6 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<NonVisualComponents>
|
||||
<Component class="javax.swing.ButtonGroup" name="caseTypeButtonGroup">
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
@ -16,30 +20,49 @@
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="1" max="-2" attributes="0">
|
||||
<Component id="jLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Component id="caseDirTextField" alignment="0" max="32767" attributes="1"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="jLabel1" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="227" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="caseDirLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="caseParentDirTextField" min="-2" pref="296" max="-2" attributes="0"/>
|
||||
<Component id="caseParentDirTextField" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="caseNameLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="caseNameTextField" min="-2" pref="296" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="26" max="-2" attributes="0"/>
|
||||
<Component id="caseNameTextField" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="caseDirTextField" alignment="0" min="-2" pref="380" max="-2" attributes="1"/>
|
||||
<Component id="multiUserSettingsWarningLabel" alignment="1" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="caseDirBrowseButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="singleUserCaseRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="multiUserCaseRadioButton" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="caseParentDirWarningLabel" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -63,7 +86,16 @@
|
||||
<Component id="jLabel2" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="caseDirTextField" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="32" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="3" attributes="0">
|
||||
<Component id="singleUserCaseRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="multiUserCaseRadioButton" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="caseParentDirWarningLabel" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="-2" pref="1" max="-2" attributes="0"/>
|
||||
<Component id="multiUserSettingsWarningLabel" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -132,5 +164,51 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="singleUserCaseRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="caseTypeButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.singleUserCaseRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="singleUserCaseRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JRadioButton" name="multiUserCaseRadioButton">
|
||||
<Properties>
|
||||
<Property name="buttonGroup" type="javax.swing.ButtonGroup" editor="org.netbeans.modules.form.RADComponent$ButtonGroupPropertyEditor">
|
||||
<ComponentRef name="caseTypeButtonGroup"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.multiUserCaseRadioButton.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="multiUserCaseRadioButtonActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="multiUserSettingsWarningLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.multiUserSettingsWarningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="caseParentDirWarningLabel">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="NewCaseVisualPanel1.caseParentDirWarningLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -24,25 +24,51 @@ import java.awt.*;
|
||||
import java.io.File;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.coreutils.PathValidator;
|
||||
|
||||
/**
|
||||
* The wizard panel for the new case creation.
|
||||
*
|
||||
* @author jantonius
|
||||
* The JPanel for the first page of the new case wizard.
|
||||
*/
|
||||
final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
|
||||
private JFileChooser fc = new JFileChooser();
|
||||
private NewCaseWizardPanel1 wizPanel;
|
||||
private final JFileChooser fileChooser = new JFileChooser();
|
||||
private final NewCaseWizardPanel1 wizPanel;
|
||||
|
||||
/**
|
||||
* Constructs the JPanel for the first page of the new case wizard.
|
||||
*
|
||||
* @param wizPanel The wizard panmel that owns this panel.
|
||||
*/
|
||||
NewCaseVisualPanel1(NewCaseWizardPanel1 wizPanel) {
|
||||
initComponents();
|
||||
this.wizPanel = wizPanel;
|
||||
caseNameTextField.getDocument().addDocumentListener(this);
|
||||
caseParentDirTextField.getDocument().addDocumentListener(this);
|
||||
initComponents();
|
||||
TextFieldListener listener = new TextFieldListener();
|
||||
caseNameTextField.getDocument().addDocumentListener(listener);
|
||||
caseParentDirTextField.getDocument().addDocumentListener(listener);
|
||||
caseParentDirWarningLabel.setVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called by the readSettings() of the wizard panel that owns this
|
||||
* UI panel so that this panel can read settings for each invocation of the
|
||||
* wizard as well.
|
||||
*/
|
||||
void readSettings() {
|
||||
caseNameTextField.setText("");
|
||||
if (UserPreferences.getIsMultiUserModeEnabled()) {
|
||||
multiUserCaseRadioButton.setEnabled(true);
|
||||
multiUserCaseRadioButton.setSelected(true);
|
||||
multiUserSettingsWarningLabel.setVisible(false);
|
||||
} else {
|
||||
multiUserCaseRadioButton.setEnabled(false);
|
||||
singleUserCaseRadioButton.setSelected(true);
|
||||
multiUserSettingsWarningLabel.setText(NbBundle.getMessage(this.getClass(), "NewCaseVisualPanel1.MultiUserDisabled.text"));
|
||||
}
|
||||
validateSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,27 +87,112 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
*
|
||||
* @return caseName the case name from the case name text field
|
||||
*/
|
||||
public String getCaseName() {
|
||||
String getCaseName() {
|
||||
return this.caseNameTextField.getText();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the the wizard panel that owns this UI panel to set the base case
|
||||
* directory to a persisted vlaue.
|
||||
*
|
||||
* @param caseParentDir The persisted path to the base case directory.
|
||||
*/
|
||||
void setCaseParentDir(String caseParentDir) {
|
||||
caseParentDirTextField.setText(caseParentDir);
|
||||
validateSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base directory that the user typed on the base directory text
|
||||
* field. Will add file separator if it was not added.
|
||||
*
|
||||
* @return baseDirectory the base directory from the case dir text field
|
||||
*/
|
||||
public String getCaseParentDir() {
|
||||
String getCaseParentDir() {
|
||||
String parentDir = this.caseParentDirTextField.getText();
|
||||
|
||||
if (parentDir.endsWith(File.separator) == false) {
|
||||
parentDir = parentDir + File.separator;
|
||||
}
|
||||
return parentDir;
|
||||
}
|
||||
|
||||
public JTextField getCaseParentDirTextField() {
|
||||
return this.caseParentDirTextField;
|
||||
/**
|
||||
* Gets the case type.
|
||||
*
|
||||
* @return CaseType as set via radio buttons
|
||||
*/
|
||||
CaseType getCaseType() {
|
||||
CaseType value = CaseType.SINGLE_USER_CASE;
|
||||
if (singleUserCaseRadioButton.isSelected()) {
|
||||
value = CaseType.SINGLE_USER_CASE;
|
||||
} else if (multiUserCaseRadioButton.isSelected()) {
|
||||
value = CaseType.MULTI_USER_CASE;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the user interacts with a child UI component of this panel,
|
||||
* this method notifies the wizard panel that owns this panel and then
|
||||
* validates the user's settings.
|
||||
*/
|
||||
private void handleUpdate() {
|
||||
wizPanel.fireChangeEvent();
|
||||
validateSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Does validation of the current settings and enables or disables the
|
||||
* "Next" button of the wizard panel that owns this panel.
|
||||
*/
|
||||
private void validateSettings() {
|
||||
/**
|
||||
* Check the base case directory for the selected case type and show a
|
||||
* warning if it is a dubious choice.
|
||||
*/
|
||||
caseParentDirWarningLabel.setVisible(false);
|
||||
String parentDir = getCaseParentDir();
|
||||
if (!PathValidator.isValid(parentDir, getCaseType())) {
|
||||
caseParentDirWarningLabel.setVisible(true);
|
||||
caseParentDirWarningLabel.setText(NbBundle.getMessage(this.getClass(), "NewCaseVisualPanel1.CaseFolderOnCDriveError.text"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the "Next" button for the wizard if there is text entered for
|
||||
* the case name and base case directory. Also make sure that multi-user
|
||||
* cases are enabled if the multi-user case radio button is selected.
|
||||
*/
|
||||
String caseName = getCaseName();
|
||||
if (!caseName.equals("") && !parentDir.equals("")) {
|
||||
caseDirTextField.setText(parentDir + caseName);
|
||||
wizPanel.setIsFinish(true);
|
||||
} else {
|
||||
caseDirTextField.setText("");
|
||||
wizPanel.setIsFinish(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles validation when the user provides input to text field components
|
||||
* of this panel.
|
||||
*/
|
||||
private class TextFieldListener implements DocumentListener {
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
handleUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
handleUpdate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
handleUpdate();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,6 +203,7 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
caseTypeButtonGroup = new javax.swing.ButtonGroup();
|
||||
jLabel1 = new javax.swing.JLabel();
|
||||
caseNameLabel = new javax.swing.JLabel();
|
||||
caseDirLabel = new javax.swing.JLabel();
|
||||
@ -100,10 +212,13 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
caseDirBrowseButton = new javax.swing.JButton();
|
||||
jLabel2 = new javax.swing.JLabel();
|
||||
caseDirTextField = new javax.swing.JTextField();
|
||||
singleUserCaseRadioButton = new javax.swing.JRadioButton();
|
||||
multiUserCaseRadioButton = new javax.swing.JRadioButton();
|
||||
multiUserSettingsWarningLabel = new javax.swing.JLabel();
|
||||
caseParentDirWarningLabel = new javax.swing.JLabel();
|
||||
|
||||
jLabel1.setFont(jLabel1.getFont().deriveFont(Font.BOLD, 14));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle
|
||||
.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.jLabel1.text_1")); // NOI18N
|
||||
jLabel1.setFont(new java.awt.Font("Tahoma", 1, 14)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.jLabel1.text_1")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(caseNameLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseNameLabel.text_1")); // NOI18N
|
||||
|
||||
@ -125,29 +240,64 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
caseDirTextField.setEditable(false);
|
||||
caseDirTextField.setText(org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseDirTextField.text_1")); // NOI18N
|
||||
|
||||
caseTypeButtonGroup.add(singleUserCaseRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(singleUserCaseRadioButton, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.singleUserCaseRadioButton.text")); // NOI18N
|
||||
singleUserCaseRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
singleUserCaseRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
caseTypeButtonGroup.add(multiUserCaseRadioButton);
|
||||
org.openide.awt.Mnemonics.setLocalizedText(multiUserCaseRadioButton, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.multiUserCaseRadioButton.text")); // NOI18N
|
||||
multiUserCaseRadioButton.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
multiUserCaseRadioButtonActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
multiUserSettingsWarningLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(multiUserSettingsWarningLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.multiUserSettingsWarningLabel.text")); // NOI18N
|
||||
|
||||
caseParentDirWarningLabel.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(caseParentDirWarningLabel, org.openide.util.NbBundle.getMessage(NewCaseVisualPanel1.class, "NewCaseVisualPanel1.caseParentDirWarningLabel.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jLabel2)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
|
||||
.addComponent(jLabel1, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(caseDirTextField, javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(jLabel1)
|
||||
.addGap(0, 227, Short.MAX_VALUE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(caseDirLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(caseParentDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 296, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
|
||||
.addComponent(caseParentDirTextField))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(caseNameLabel)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(caseNameTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 296, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(caseDirTextField, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 380, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addGap(26, 26, 26)
|
||||
.addComponent(caseNameTextField))
|
||||
.addComponent(multiUserSettingsWarningLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(caseDirBrowseButton)))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addContainerGap())
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addComponent(singleUserCaseRadioButton)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(multiUserCaseRadioButton))
|
||||
.addComponent(caseParentDirWarningLabel))
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -167,7 +317,15 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
.addComponent(jLabel2)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(caseDirTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(32, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(singleUserCaseRadioButton)
|
||||
.addComponent(multiUserCaseRadioButton))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(caseParentDirWarningLabel)
|
||||
.addGap(1, 1, 1)
|
||||
.addComponent(multiUserSettingsWarningLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
@ -179,23 +337,27 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
* @param evt the action event
|
||||
*/
|
||||
private void caseDirBrowseButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_caseDirBrowseButtonActionPerformed
|
||||
// show the directory chooser where the case directory will be created
|
||||
fc.setDragEnabled(false);
|
||||
fileChooser.setDragEnabled(false);
|
||||
if (!caseParentDirTextField.getText().trim().equals("")) {
|
||||
fc.setCurrentDirectory(new File(caseParentDirTextField.getText()));
|
||||
fileChooser.setCurrentDirectory(new File(caseParentDirTextField.getText()));
|
||||
}
|
||||
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
//fc.setSelectedFile(new File("C:\\Program Files\\"));
|
||||
//disableTextField(fc); // disable all the text field on the file chooser
|
||||
|
||||
int returnValue = fc.showDialog((Component) evt.getSource(), NbBundle.getMessage(this.getClass(),
|
||||
fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
|
||||
int choice = fileChooser.showDialog((Component) evt.getSource(), NbBundle.getMessage(this.getClass(),
|
||||
"NewCaseVisualPanel1.caseDirBrowse.selectButton.text"));
|
||||
if (returnValue == JFileChooser.APPROVE_OPTION) {
|
||||
String path = fc.getSelectedFile().getPath();
|
||||
caseParentDirTextField.setText(path); // put the path to the textfield
|
||||
if (JFileChooser.APPROVE_OPTION == choice) {
|
||||
String path = fileChooser.getSelectedFile().getPath();
|
||||
caseParentDirTextField.setText(path);
|
||||
}
|
||||
}//GEN-LAST:event_caseDirBrowseButtonActionPerformed
|
||||
|
||||
private void singleUserCaseRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_singleUserCaseRadioButtonActionPerformed
|
||||
handleUpdate();
|
||||
}//GEN-LAST:event_singleUserCaseRadioButtonActionPerformed
|
||||
|
||||
private void multiUserCaseRadioButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_multiUserCaseRadioButtonActionPerformed
|
||||
handleUpdate();
|
||||
}//GEN-LAST:event_multiUserCaseRadioButtonActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton caseDirBrowseButton;
|
||||
private javax.swing.JLabel caseDirLabel;
|
||||
@ -203,8 +365,13 @@ final class NewCaseVisualPanel1 extends JPanel implements DocumentListener {
|
||||
private javax.swing.JLabel caseNameLabel;
|
||||
private javax.swing.JTextField caseNameTextField;
|
||||
private javax.swing.JTextField caseParentDirTextField;
|
||||
private javax.swing.JLabel caseParentDirWarningLabel;
|
||||
private javax.swing.ButtonGroup caseTypeButtonGroup;
|
||||
private javax.swing.JLabel jLabel1;
|
||||
private javax.swing.JLabel jLabel2;
|
||||
private javax.swing.JRadioButton multiUserCaseRadioButton;
|
||||
private javax.swing.JLabel multiUserSettingsWarningLabel;
|
||||
private javax.swing.JRadioButton singleUserCaseRadioButton;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -24,6 +24,8 @@ import java.io.File;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.SwingWorker;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.DialogDescriptor;
|
||||
import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
@ -33,6 +35,12 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.actions.CallableSystemAction;
|
||||
import org.openide.util.actions.SystemAction;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.JOptionPane;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskData.DbType;
|
||||
|
||||
/**
|
||||
* Action to open the New Case wizard.
|
||||
@ -74,7 +82,7 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
* The method to perform new case creation
|
||||
*/
|
||||
private void newCaseAction() {
|
||||
WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
|
||||
final WizardDescriptor wizardDescriptor = new WizardDescriptor(getPanels());
|
||||
// {0} will be replaced by WizardDesriptor.Panel.getComponent().getName()
|
||||
wizardDescriptor.setTitleFormat(new MessageFormat("{0}"));
|
||||
wizardDescriptor.setTitle(NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.newCase.windowTitle.text"));
|
||||
@ -82,32 +90,67 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
dialog.setVisible(true);
|
||||
dialog.toFront();
|
||||
|
||||
boolean finished = wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION; // check if it finishes (it's not cancelled)
|
||||
boolean isCancelled = wizardDescriptor.getValue() == WizardDescriptor.CANCEL_OPTION; // check if the "Cancel" button is pressed
|
||||
if (wizardDescriptor.getValue() == WizardDescriptor.FINISH_OPTION) {
|
||||
new SwingWorker<Void, Void>() {
|
||||
|
||||
// if the finish button is pressed (not cancelled)
|
||||
if (finished) {
|
||||
// now start the 'Add Image' wizard
|
||||
//TODO fix for local
|
||||
@Override
|
||||
protected Void doInBackground() throws Exception {
|
||||
// Create case.
|
||||
|
||||
String caseNumber = (String) wizardDescriptor.getProperty("caseNumber"); //NON-NLS
|
||||
String examiner = (String) wizardDescriptor.getProperty("caseExaminer"); //NON-NLS
|
||||
final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS
|
||||
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
|
||||
CaseType caseType = CaseType.values()[(int) wizardDescriptor.getProperty("caseType")]; //NON-NLS
|
||||
|
||||
Case.create(createdDirectory, caseName, caseNumber, examiner, caseType);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
try {
|
||||
get();
|
||||
CaseType currentCaseType = CaseType.values()[(int) wizardDescriptor.getProperty("caseType")]; //NON-NLS
|
||||
CaseDbConnectionInfo info = UserPreferences.getDatabaseConnectionInfo();
|
||||
if ((currentCaseType == CaseType.SINGLE_USER_CASE) || ((info.getDbType() != DbType.SQLITE) && SleuthkitCase.tryConnectOld(info.getHost(), info.getPort(), info.getUserName(), info.getPassword(), info.getDbType()))) {
|
||||
AddImageAction addImageAction = SystemAction.get(AddImageAction.class);
|
||||
addImageAction.actionPerformed(null);
|
||||
} else {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.databaseProblem1.text"),
|
||||
NbBundle.getMessage(this.getClass(), "NewCaseWizardAction.databaseProblem2.text"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
}
|
||||
|
||||
// if Cancel button is pressed
|
||||
if (isCancelled) {
|
||||
} catch (Exception ex) {
|
||||
final String caseName = (String) wizardDescriptor.getProperty("caseName"); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null, NbBundle.getMessage(this.getClass(),
|
||||
"CaseCreateAction.msgDlg.cantCreateCase.msg") + " " + caseName,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"CaseOpenAction.msgDlg.cantOpenCase.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
});
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
doFailedCaseCleanup(wizardDescriptor);
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void doFailedCaseCleanup(WizardDescriptor wizardDescriptor) {
|
||||
String createdDirectory = (String) wizardDescriptor.getProperty("createdDirectory"); //NON-NLS
|
||||
|
||||
if (createdDirectory != null) {
|
||||
logger.log(Level.INFO, "Deleting a created case directory due to isCancelled set, dir: " + createdDirectory); //NON-NLS
|
||||
logger.log(Level.INFO, "Deleting a created case directory due to an error, dir: {0}", createdDirectory); //NON-NLS
|
||||
Case.deleteCaseDirectory(new File(createdDirectory));
|
||||
}
|
||||
// if there's case opened, close the case
|
||||
if (Case.existsCurrentCase()) {
|
||||
// close the previous case if there's any
|
||||
CaseCloseAction closeCase = SystemAction.get(CaseCloseAction.class);
|
||||
closeCase.actionPerformed(null);
|
||||
}
|
||||
}
|
||||
panels = null; // reset the panel
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,7 +174,7 @@ final class NewCaseWizardAction extends CallableSystemAction {
|
||||
if (c instanceof JComponent) { // assume Swing components
|
||||
JComponent jc = (JComponent) c;
|
||||
// Sets step number of a component
|
||||
jc.putClientProperty("WizardPanel_contentSelectedIndex", new Integer(i));
|
||||
jc.putClientProperty("WizardPanel_contentSelectedIndex", i);
|
||||
// Sets steps names for a panel
|
||||
jc.putClientProperty("WizardPanel_contentData", steps);
|
||||
// Turn on subtitle creation on each step
|
||||
|
@ -33,8 +33,8 @@ import org.openide.DialogDisplayer;
|
||||
import org.openide.NotifyDescriptor;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.WizardValidationException;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
|
||||
|
||||
/**
|
||||
@ -170,7 +170,8 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
NewCaseVisualPanel1 component = getComponent();
|
||||
try {
|
||||
String lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE);
|
||||
component.getCaseParentDirTextField().setText(lastBaseDirectory);
|
||||
component.setCaseParentDir(lastBaseDirectory);
|
||||
component.readSettings();
|
||||
createdDirectory = (String) settings.getProperty("createdDirectory"); //NON-NLS
|
||||
if (createdDirectory != null && !createdDirectory.equals("")) {
|
||||
logger.log(Level.INFO, "Deleting a case dir in readSettings(): " + createdDirectory); //NON-NLS
|
||||
@ -192,9 +193,12 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
*/
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor settings) {
|
||||
CaseType caseType = getComponent().getCaseType();
|
||||
settings.putProperty("caseName", getComponent().getCaseName()); //NON-NLS
|
||||
settings.putProperty("caseParentDir", getComponent().getCaseParentDir()); //NON-NLS
|
||||
settings.putProperty("createdDirectory", createdDirectory); //NON-NLS
|
||||
settings.putProperty("caseType", caseType.ordinal()); //NON-NLS
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, ModuleSettings.CURRENT_CASE_TYPE, caseType.toString());
|
||||
ModuleSettings.setConfigSetting(ModuleSettings.MAIN_SETTINGS, PROP_BASECASE, getComponent().getCaseParentDir());
|
||||
}
|
||||
|
||||
@ -237,7 +241,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
if (res2 != null && res2 == DialogDescriptor.YES_OPTION) {
|
||||
// if user say yes
|
||||
try {
|
||||
createDirectory(caseDirPath);
|
||||
createDirectory(caseDirPath, getComponent().getCaseType());
|
||||
} catch (Exception ex) {
|
||||
String errorMsg = NbBundle.getMessage(this.getClass(),
|
||||
"NewCaseWizardPanel1.validate.errMsg.cantCreateParDir.msg",
|
||||
@ -254,7 +258,7 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
createDirectory(caseDirPath);
|
||||
createDirectory(caseDirPath, getComponent().getCaseType());
|
||||
} catch (Exception ex) {
|
||||
String errorMsg = NbBundle
|
||||
.getMessage(this.getClass(), "NewCaseWizardPanel1.validate.errMsg.cantCreateDir");
|
||||
@ -279,11 +283,11 @@ class NewCaseWizardPanel1 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
/*
|
||||
* create the directory and create a new case
|
||||
*/
|
||||
private void createDirectory(final String caseDirPath) throws WizardValidationException {
|
||||
// try to create the directory with the case name in the choosen parent directory
|
||||
private void createDirectory(final String caseDirPath, CaseType caseType) throws WizardValidationException {
|
||||
// try to create the directory with the case name in the chosen parent directory
|
||||
boolean success = false;
|
||||
try {
|
||||
Case.createCaseDirectory(caseDirPath);
|
||||
Case.createCaseDirectory(caseDirPath, caseType);
|
||||
success = true;
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.SEVERE, "Could not createDirectory for the case, ", ex); //NON-NLS
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -21,14 +21,14 @@ package org.sleuthkit.autopsy.casemodule;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import org.openide.WizardDescriptor;
|
||||
import org.openide.WizardValidationException;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.NbBundle;
|
||||
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
|
||||
@ -48,6 +48,7 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
private String caseName;
|
||||
private String caseDir;
|
||||
private String createdDirectory;
|
||||
private CaseType caseType;
|
||||
|
||||
/**
|
||||
* Get the visual component for the panel. In this template, the component
|
||||
@ -129,7 +130,7 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
protected final void fireChangeEvent() {
|
||||
Iterator<ChangeListener> it;
|
||||
synchronized (listeners) {
|
||||
it = new HashSet<ChangeListener>(listeners).iterator();
|
||||
it = new HashSet<>(listeners).iterator();
|
||||
}
|
||||
ChangeEvent ev = new ChangeEvent(this);
|
||||
while (it.hasNext()) {
|
||||
@ -154,6 +155,7 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
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
|
||||
}
|
||||
|
||||
/**
|
||||
@ -167,34 +169,13 @@ class NewCaseWizardPanel2 implements WizardDescriptor.ValidatingPanel<WizardDesc
|
||||
*/
|
||||
@Override
|
||||
public void storeSettings(WizardDescriptor settings) {
|
||||
NewCaseVisualPanel2 currentComponent = getComponent();
|
||||
settings.putProperty("caseNumber", currentComponent.getCaseNumber());
|
||||
settings.putProperty("caseExaminer", currentComponent.getExaminer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate() throws WizardValidationException {
|
||||
|
||||
NewCaseVisualPanel2 currentComponent = getComponent();
|
||||
final String caseNumber = currentComponent.getCaseNumber();
|
||||
final String examiner = currentComponent.getExaminer();
|
||||
try {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Case.create(createdDirectory, caseName, caseNumber, examiner);
|
||||
} catch (Exception ex) {
|
||||
Exceptions.printStackTrace(ex);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
//Case.create(createdDirectory, caseName, caseNumber, examiner);
|
||||
} catch (Exception ex) {
|
||||
throw new WizardValidationException(this.getComponent(),
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"NewCaseWizardPanel2.validate.errCreateCase.msg"),
|
||||
null);
|
||||
}
|
||||
WindowManager.getDefault().getMainWindow().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -24,8 +24,8 @@ import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JTable;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.table.AbstractTableModel;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@ -37,7 +37,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
|
||||
static String[] caseNames;
|
||||
static String[] casePaths;
|
||||
private static Logger logger = Logger.getLogger(OpenRecentCasePanel.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(OpenRecentCasePanel.class.getName());
|
||||
private static OpenRecentCasePanel instance;
|
||||
private RecentCasesTableModel model;
|
||||
|
||||
@ -184,8 +184,8 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
logger.log(Level.INFO, "No Case paths exist, cannot open the case"); //NON-NLS
|
||||
return;
|
||||
}
|
||||
String casePath = casePaths[imagesTable.getSelectedRow()];
|
||||
String caseName = caseNames[imagesTable.getSelectedRow()];
|
||||
final String casePath = casePaths[imagesTable.getSelectedRow()];
|
||||
final String caseName = caseNames[imagesTable.getSelectedRow()];
|
||||
if (!casePath.equals("")) {
|
||||
// Close the startup menu
|
||||
try {
|
||||
@ -195,13 +195,12 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS
|
||||
}
|
||||
// Open the recent cases
|
||||
try {
|
||||
if (caseName.equals("") || casePath.equals("") || (!new File(casePath).exists())) {
|
||||
JOptionPane.showMessageDialog(null,
|
||||
NbBundle.getMessage(OpenRecentCasePanel.class,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"OpenRecentCasePanel.openCase.msgDlg.caseDoesntExist.msg",
|
||||
caseName),
|
||||
NbBundle.getMessage(OpenRecentCasePanel.class,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"OpenRecentCasePanel.openCase.msgDlg.err"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
RecentCases.getInstance().removeRecentCase(caseName, casePath); // remove the recent case if it doesn't exist anymore
|
||||
@ -212,10 +211,18 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
} else {
|
||||
Case.open(casePath); // open the case
|
||||
}
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Case.open(casePath);
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.WARNING, "Error: couldn't open case: " + caseName, ex); //NON-NLS
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null, ex.getMessage(), NbBundle.getMessage(this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), JOptionPane.ERROR_MESSAGE);
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -286,7 +293,7 @@ class OpenRecentCasePanel extends javax.swing.JPanel {
|
||||
ret = shortenPath(casePaths[rowIndex]);
|
||||
break;
|
||||
default:
|
||||
logger.log(Level.SEVERE, "Invalid table column index: " + columnIndex); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Invalid table column index: {0}", columnIndex); //NON-NLS
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2014 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -22,11 +22,10 @@ import java.awt.EventQueue;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.io.File;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* This class is used to add the action to the recent case menu item. When the
|
||||
@ -34,8 +33,8 @@ import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
*/
|
||||
class RecentItems implements ActionListener {
|
||||
|
||||
String caseName;
|
||||
String casePath;
|
||||
final String caseName;
|
||||
final String casePath;
|
||||
private JPanel caller; // for error handling
|
||||
|
||||
/**
|
||||
@ -65,22 +64,25 @@ class RecentItems implements ActionListener {
|
||||
|
||||
//if case is not opened, open the start window
|
||||
if (Case.isCaseOpen() == false) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
EventQueue.invokeLater(() -> {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
} else {
|
||||
new Thread(() -> {
|
||||
// Create case.
|
||||
try {
|
||||
Case.open(casePath); // open the case
|
||||
Case.open(casePath);
|
||||
} catch (CaseActionException ex) {
|
||||
Logger.getLogger(RecentItems.class.getName()).log(Level.WARNING, "Error: Couldn't open recent case at " + casePath, ex); //NON-NLS
|
||||
}
|
||||
SwingUtilities.invokeLater(() -> {
|
||||
JOptionPane.showMessageDialog(null, ex.getMessage(), NbBundle.getMessage(RecentItems.this.getClass(), "CaseOpenAction.msgDlg.cantOpenCase.title"), JOptionPane.ERROR_MESSAGE);
|
||||
if (!Case.isCaseOpen()) {
|
||||
StartupWindowProvider.getInstance().open();
|
||||
}
|
||||
});
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -59,6 +59,7 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
|
||||
|
||||
// set the location of the popUp Window on the center of the screen
|
||||
setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2);
|
||||
setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
|
||||
welcomeWindow = new CueBannerPanel();
|
||||
|
||||
@ -80,6 +81,7 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa
|
||||
@Override
|
||||
public void open() {
|
||||
welcomeWindow.refresh();
|
||||
setLocationRelativeTo(WindowManager.getDefault().getMainWindow());
|
||||
setVisible(true);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -33,7 +33,9 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
int length;
|
||||
static boolean hasRecentCase = false;
|
||||
|
||||
/** the constructor */
|
||||
/**
|
||||
* the constructor
|
||||
*/
|
||||
UpdateRecentCases() {
|
||||
// display last 5 cases.
|
||||
length = RecentCases.LENGTH - 1;
|
||||
@ -60,7 +62,7 @@ class UpdateRecentCases extends JMenuItem implements DynamicMenuContent {
|
||||
menuItem.setActionCommand(caseName[i].toUpperCase());
|
||||
menuItem.addActionListener(new RecentItems(caseName[i], casePath[i]));
|
||||
comps[i] = menuItem;
|
||||
hasRecentCase = hasRecentCase || true;
|
||||
hasRecentCase = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012 Basis Technology Corp.
|
||||
* Copyright 2012-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -29,10 +29,10 @@ import javax.xml.parsers.*;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.dom.*;
|
||||
import javax.xml.transform.stream.*;
|
||||
import org.openide.util.Exceptions;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.casemodule.Case.CaseType;
|
||||
import org.sleuthkit.autopsy.core.RuntimeProperties;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.XMLUtil;
|
||||
import org.w3c.dom.*;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
@ -60,6 +60,7 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
final static String SCHEMA_VERSION_NAME = "SchemaVersion"; //NON-NLS
|
||||
final static String AUTOPSY_CRVERSION_NAME = "AutopsyCreatedVersion"; //NON-NLS
|
||||
final static String AUTOPSY_MVERSION_NAME = "AutopsySavedVersion"; //NON-NLS
|
||||
final static String CASE_TEXT_INDEX_NAME = "TextIndexName"; //NON-NLS
|
||||
// folders inside case directory
|
||||
final static String LOG_FOLDER_NAME = "LogFolder"; //NON-NLS
|
||||
final static String LOG_FOLDER_RELPATH = "Log"; //NON-NLS
|
||||
@ -69,6 +70,8 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
final static String EXPORT_FOLDER_RELPATH = "Export"; //NON-NLS
|
||||
final static String CACHE_FOLDER_NAME = "CacheFolder"; //NON-NLS
|
||||
final static String CACHE_FOLDER_RELPATH = "Cache"; //NON-NLS
|
||||
final static String CASE_TYPE = "CaseType"; //NON-NLS
|
||||
final static String DATABASE_NAME = "DatabaseName"; //NON-NLS
|
||||
// folders attribute
|
||||
final static String RELATIVE_NAME = "Relative"; // relevant path info NON-NLS
|
||||
// folder attr values
|
||||
@ -77,23 +80,26 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
// the document
|
||||
private Document doc;
|
||||
// general info
|
||||
private DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
|
||||
private final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss (z)");
|
||||
private String caseDirPath; // case directory path
|
||||
private String caseName; // case name
|
||||
private String caseNumber; // case number
|
||||
private String examiner; // examiner name
|
||||
private String schemaVersion = "1.0";
|
||||
private String autopsySavedVersion;
|
||||
private final String schemaVersion = "1.0";
|
||||
private final String autopsySavedVersion;
|
||||
private CaseType caseType; // The type of case: local or shared
|
||||
private String dbName; // The name of the database
|
||||
private String textIndexName; // The name of the index where extracted text is stored.
|
||||
|
||||
// for error handling
|
||||
private JPanel caller;
|
||||
private String className = this.getClass().toString();
|
||||
private final String className = this.getClass().toString();
|
||||
private static final Logger logger = Logger.getLogger(XMLCaseManagement.class.getName());
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
XMLCaseManagement() {
|
||||
// System.setProperty("netbeans.buildnumber", autopsyVer); // set the current autopsy version // moved to CoreComponents installer
|
||||
public XMLCaseManagement() {
|
||||
autopsySavedVersion = System.getProperty("netbeans.buildnumber");
|
||||
}
|
||||
|
||||
@ -148,6 +154,23 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the created date on the XML configuration file. This method is for
|
||||
* preserving the created date when converting a case from single-user to
|
||||
* multi-user.
|
||||
*
|
||||
* @param createdDate the date the case was originally created
|
||||
*
|
||||
* @throws org.sleuthkit.autopsy.casemodule.CaseActionException
|
||||
*/
|
||||
public void setCreatedDate(String createdDate) throws CaseActionException {
|
||||
String newDate = dateFormat.format(new Date());
|
||||
Element rootEl = getRootElement();
|
||||
rootEl.getElementsByTagName(CREATED_DATE_NAME).item(0).setTextContent(createdDate);
|
||||
rootEl.getElementsByTagName(MODIFIED_DATE_NAME).item(0).setTextContent(newDate);
|
||||
writeFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the examiner on the XML configuration file
|
||||
*
|
||||
@ -187,6 +210,89 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
caseNumber = givenCaseNumber; // change this to change the xml file if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the case type internally (on local variable in this class)
|
||||
*
|
||||
* @param givenCaseType the new case type
|
||||
*/
|
||||
private void setCaseType(CaseType givenCaseType) {
|
||||
caseType = givenCaseType; // change this to change the xml file if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the case Type from the document handler. Defaults to local if it
|
||||
* can't figure it out.
|
||||
*
|
||||
* @return caseType from the document handler
|
||||
*/
|
||||
public CaseType getCaseType() {
|
||||
if (doc == null) {
|
||||
return CaseType.SINGLE_USER_CASE;
|
||||
} else {
|
||||
if (getCaseElement().getElementsByTagName(CASE_TYPE).getLength() > 0) {
|
||||
Element nameElement = (Element) getCaseElement().getElementsByTagName(CASE_TYPE).item(0);
|
||||
return CaseType.fromString(nameElement.getTextContent());
|
||||
} else {
|
||||
return CaseType.SINGLE_USER_CASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the database name internally (on local variable in this class)
|
||||
*
|
||||
* @param givenDbName the new db name
|
||||
*/
|
||||
private void setDatabaseName(String givenDbName) {
|
||||
dbName = givenDbName; // change this to change the xml file if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database name from the document handler
|
||||
*
|
||||
* @return the database name
|
||||
*/
|
||||
public String getDatabaseName() {
|
||||
if (doc == null) {
|
||||
return "";
|
||||
} else {
|
||||
if (getCaseElement().getElementsByTagName(DATABASE_NAME).getLength() > 0) {
|
||||
Element nameElement = (Element) getCaseElement().getElementsByTagName(DATABASE_NAME).item(0);
|
||||
return nameElement.getTextContent();
|
||||
} else {
|
||||
return ""; /// couldn't find one, so return a blank name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text index name internally (on local variable in this class)
|
||||
*
|
||||
* @param textIndexName the new name for the index where extracted text is
|
||||
* stored for the case.
|
||||
*/
|
||||
private void setTextIndexName(String textIndexName) {
|
||||
this.textIndexName = textIndexName; // change this to change the xml file if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the index where extracted text is stored.
|
||||
*
|
||||
* @return the index name
|
||||
*/
|
||||
public String getTextIndexName() {
|
||||
if (doc == null) {
|
||||
return "";
|
||||
} else {
|
||||
if (getCaseElement().getElementsByTagName(CASE_TEXT_INDEX_NAME).getLength() > 0) {
|
||||
Element nameElement = (Element) getCaseElement().getElementsByTagName(CASE_TEXT_INDEX_NAME).item(0);
|
||||
return nameElement.getTextContent();
|
||||
} else {
|
||||
return ""; /// couldn't find one, so return a blank index name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the examiner name internally (on local variable in this class)
|
||||
*
|
||||
@ -282,7 +388,7 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
*
|
||||
* @return createdDate the creation date of this case
|
||||
*/
|
||||
protected String getCreatedDate() {
|
||||
public String getCreatedDate() {
|
||||
if (doc != null) {
|
||||
Element crDateElement = (Element) getRootElement().getElementsByTagName(CREATED_DATE_NAME).item(0);
|
||||
return crDateElement.getTextContent();
|
||||
@ -438,12 +544,16 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
* the schema version 1.0
|
||||
*
|
||||
* @param dirPath case directory path
|
||||
* @param caseName the name of the config file to be located in the case
|
||||
* directory
|
||||
* @param caseName the name of the config file to be located in the
|
||||
* case directory
|
||||
* @param examiner examiner for the case (optional, can be empty string
|
||||
* @param caseNumber case number (optional), can be empty
|
||||
* @param dbName the name of the database. Could be a local path,
|
||||
* could be a Postgre db name.
|
||||
* @param textIndexName The name of the index where extracted text is
|
||||
* stored.
|
||||
*/
|
||||
protected void create(String dirPath, String caseName, String examiner, String caseNumber) throws CaseActionException {
|
||||
public void create(String dirPath, String caseName, String examiner, String caseNumber, CaseType caseType, String dbName, String textIndexName) throws CaseActionException {
|
||||
clear(); // clear the previous data
|
||||
|
||||
// set the case Name and Directory and the parent directory
|
||||
@ -451,6 +561,9 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
setName(caseName);
|
||||
setExaminer(examiner);
|
||||
setNumber(caseNumber);
|
||||
setCaseType(caseType);
|
||||
setDatabaseName(dbName);
|
||||
setTextIndexName(textIndexName);
|
||||
DocumentBuilder docBuilder;
|
||||
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
|
||||
|
||||
@ -522,6 +635,18 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
cacheElement.setAttribute(RELATIVE_NAME, "true"); //NON-NLS
|
||||
caseElement.appendChild(cacheElement);
|
||||
|
||||
Element typeElement = doc.createElement(CASE_TYPE); // <CaseType> ... </CaseType>
|
||||
typeElement.appendChild(doc.createTextNode(caseType.toString()));
|
||||
caseElement.appendChild(typeElement);
|
||||
|
||||
Element dbNameElement = doc.createElement(DATABASE_NAME); // <DatabaseName> ... </DatabaseName>
|
||||
dbNameElement.appendChild(doc.createTextNode(dbName));
|
||||
caseElement.appendChild(dbNameElement);
|
||||
|
||||
Element indexNameElement = doc.createElement(CASE_TEXT_INDEX_NAME); // <TextIndexName> ... </TextIndexName>
|
||||
indexNameElement.appendChild(doc.createTextNode(textIndexName));
|
||||
caseElement.appendChild(indexNameElement);
|
||||
|
||||
// write more code if needed ...
|
||||
}
|
||||
|
||||
@ -597,19 +722,11 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
File file = new File(conFilePath);
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
DocumentBuilder db = null;
|
||||
DocumentBuilder db;
|
||||
try {
|
||||
db = dbf.newDocumentBuilder();
|
||||
doc = db.parse(file);
|
||||
} catch (ParserConfigurationException ex) {
|
||||
throw new CaseActionException(
|
||||
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.open.exception.errReadXMLFile.msg",
|
||||
conFilePath), ex);
|
||||
} catch (SAXException ex) {
|
||||
throw new CaseActionException(
|
||||
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.open.exception.errReadXMLFile.msg",
|
||||
conFilePath), ex);
|
||||
} catch (IOException ex) {
|
||||
} catch (ParserConfigurationException | SAXException | IOException ex) {
|
||||
throw new CaseActionException(
|
||||
NbBundle.getMessage(this.getClass(), "XMLCaseManagement.open.exception.errReadXMLFile.msg",
|
||||
conFilePath), ex);
|
||||
@ -618,10 +735,10 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
doc.getDocumentElement().normalize();
|
||||
doc.getDocumentElement().normalize();
|
||||
|
||||
if (!XMLUtil.xmlIsValid(doc, XMLCaseManagement.class, XSDFILE)) {
|
||||
logger.log(Level.WARNING, "Could not validate against [" + XSDFILE + "], results may not accurate"); //NON-NLS
|
||||
}
|
||||
|
||||
// TODO: Restore later
|
||||
// if (!XMLUtil.xmlIsValid(doc, XMLCaseManagement.class, XSDFILE)) {
|
||||
// logger.log(Level.WARNING, "Could not validate against [" + XSDFILE + "], results may not accurate"); //NON-NLS
|
||||
// }
|
||||
Element rootEl = doc.getDocumentElement();
|
||||
String rootName = rootEl.getNodeName();
|
||||
|
||||
@ -629,6 +746,8 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
if (!rootName.equals(TOP_ROOT_NAME)) {
|
||||
// throw an error ...
|
||||
clear();
|
||||
if (RuntimeProperties.coreComponentsAreActive()) {
|
||||
|
||||
JOptionPane.showMessageDialog(caller,
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"XMLCaseManagement.open.msgDlg.notAutCase.msg",
|
||||
@ -636,6 +755,7 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
NbBundle.getMessage(this.getClass(),
|
||||
"XMLCaseManagement.open.msgDlg.notAutCase.title"),
|
||||
JOptionPane.ERROR_MESSAGE);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Autopsy Created Version
|
||||
@ -687,5 +807,8 @@ class XMLCaseManagement implements CaseConfigFileInterface {
|
||||
caseName = "";
|
||||
caseNumber = "";
|
||||
examiner = "";
|
||||
caseType = CaseType.SINGLE_USER_CASE;
|
||||
dbName = "";
|
||||
textIndexName = "";
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
|
||||
/**
|
||||
* Event published when a data source is being added to a case.
|
||||
*/
|
||||
@Immutable
|
||||
public final class AddingDataSourceEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final UUID dataSourceId;
|
||||
|
||||
/**
|
||||
* Constructs an event published when a data source is being added to a
|
||||
* case.
|
||||
*
|
||||
* @param dataSourceId A unique identifier associated with the data source.
|
||||
* Used to pair this AddingDataSourceEvent with a
|
||||
* DataSourceAddedEvent or a
|
||||
* AddingDataSourceFailedEvent.
|
||||
*/
|
||||
public AddingDataSourceEvent(UUID dataSourceId) {
|
||||
super(Case.Events.ADDING_DATA_SOURCE.toString(), null, null);
|
||||
this.dataSourceId = dataSourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique id for the data source used to pair this
|
||||
* AddindDataSourceEvent with a a DataSourceAddedEvent or a
|
||||
* AddingDataSourceFailedEvent.
|
||||
*
|
||||
* @return The unique id.
|
||||
*/
|
||||
public UUID getDataSourceId() {
|
||||
return dataSourceId;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
|
||||
/**
|
||||
* Event published when an attempt to add a data source to a case fails.
|
||||
*/
|
||||
@Immutable
|
||||
public final class AddingDataSourceFailedEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final UUID dataSourceId;
|
||||
|
||||
/**
|
||||
* Constructs an event published when an attempt to add a data source to a
|
||||
* case fails.
|
||||
*
|
||||
* @param dataSourceId A unique identifier associated with the data source.
|
||||
* Used to pair this AddingDataSourceFailedEvent with a
|
||||
* AddingDataSourceEvent.
|
||||
*/
|
||||
public AddingDataSourceFailedEvent(UUID dataSourceId) {
|
||||
super(Case.Events.ADDING_DATA_SOURCE_FAILED.toString(), null, null);
|
||||
this.dataSourceId = dataSourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique id for the data source used to pair this
|
||||
* AddingDataSourceFailedEvent with a AddingDataSourceEvent.
|
||||
*
|
||||
* @return The unique id.
|
||||
*/
|
||||
public UUID getDataSourceId() {
|
||||
return dataSourceId;
|
||||
}
|
||||
|
||||
}
|
@ -16,18 +16,36 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.events;
|
||||
package org.sleuthkit.autopsy.casemodule.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Event sent when a black board artifact tag is added.
|
||||
*/
|
||||
public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent<BlackboardArtifactTag> {
|
||||
@Immutable
|
||||
public class BlackBoardArtifactTagAddedEvent extends TagAddedEvent<BlackboardArtifactTag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public BlackBoardArtifactTagAddedEvent(BlackboardArtifactTag newTag) {
|
||||
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString(), newTag
|
||||
);
|
||||
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_ADDED.toString(), newTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the BlackboardArtifactTag that was added by its id
|
||||
*
|
||||
* @return BlackboardArtifactTag that was added
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
@Override
|
||||
BlackboardArtifactTag getTagByID() throws IllegalStateException, TskCoreException {
|
||||
return Case.getCurrentCase().getServices().getTagsManager().getBlackboardArtifactTagByTagID(getTagID());
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifactTag;
|
||||
|
||||
/**
|
||||
* Event that is fired when a black board artifact tag is deleted.
|
||||
*/
|
||||
@Immutable
|
||||
public class BlackBoardArtifactTagDeletedEvent extends TagDeletedEvent<BlackboardArtifactTag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public BlackBoardArtifactTagDeletedEvent(BlackboardArtifactTag deletedTag) {
|
||||
super(Case.Events.BLACKBOARD_ARTIFACT_TAG_DELETED.toString(), new DeletedBlackboardArtifactTagInfo(deletedTag));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*
|
||||
* @return the DeletedBlackboardArtifactTagInfo for the deleted tag
|
||||
*/
|
||||
@Override
|
||||
public DeletedBlackboardArtifactTagInfo getDeletedTagInfo() {
|
||||
return (DeletedBlackboardArtifactTagInfo) getOldValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of {@link DeletedTagInfo} for BlackBoardArtifactTags that
|
||||
* includes artifact related info.
|
||||
*/
|
||||
@Immutable
|
||||
public static class DeletedBlackboardArtifactTagInfo extends DeletedTagInfo<BlackboardArtifactTag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final long contentID;
|
||||
|
||||
private final long artifactID;
|
||||
|
||||
private DeletedBlackboardArtifactTagInfo(BlackboardArtifactTag deletedTag) {
|
||||
super(deletedTag);
|
||||
artifactID = deletedTag.getArtifact().getArtifactID();
|
||||
contentID = deletedTag.getContent().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentID() {
|
||||
return contentID;
|
||||
}
|
||||
|
||||
public long getArtifactID() {
|
||||
return artifactID;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,20 +16,35 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.events;
|
||||
package org.sleuthkit.autopsy.casemodule.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* An event that is fired when a ContentTag is added.
|
||||
*/
|
||||
@Immutable
|
||||
public class ContentTagAddedEvent extends TagAddedEvent<ContentTag> {
|
||||
public class ContentTagAddedEvent extends TagAddedEvent<ContentTag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ContentTagAddedEvent(ContentTag newTag) {
|
||||
super(Case.Events.CONTENT_TAG_ADDED.toString(), newTag);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the ContentTag that was added by its id
|
||||
*
|
||||
* @return ContentTag that was added
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
ContentTag getTagByID() throws IllegalStateException, TskCoreException {
|
||||
return Case.getCurrentCase().getServices().getTagsManager().getContentTagByTagID(getTagID());
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
|
||||
/**
|
||||
* An event that is fired when a ContentTag is deleted.
|
||||
*/
|
||||
@Immutable
|
||||
public class ContentTagDeletedEvent extends TagDeletedEvent<ContentTag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ContentTagDeletedEvent(ContentTag deletedTag) {
|
||||
super(Case.Events.CONTENT_TAG_DELETED.toString(), new DeletedContentTagInfo(deletedTag));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc }
|
||||
*
|
||||
* @return the DeletedContentTagInfo for the deleted tag
|
||||
*/
|
||||
@Override
|
||||
public DeletedContentTagInfo getDeletedTagInfo() {
|
||||
return (DeletedContentTagInfo) getOldValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension of {@link DeletedTagInfo} for BlackBoardArtifactTags that
|
||||
* includes byte offset related info.
|
||||
*/
|
||||
@Immutable
|
||||
public static class DeletedContentTagInfo extends DeletedTagInfo<ContentTag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final long contentID;
|
||||
private final long beginByteOffset;
|
||||
private final long endByteOffset;
|
||||
|
||||
private DeletedContentTagInfo(ContentTag deletedTag) {
|
||||
super(deletedTag);
|
||||
beginByteOffset = deletedTag.getBeginByteOffset();
|
||||
endByteOffset = deletedTag.getEndByteOffset();
|
||||
contentID = deletedTag.getContent().getId();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getContentID() {
|
||||
return contentID;
|
||||
}
|
||||
|
||||
public long getBeginByteOffset() {
|
||||
return beginByteOffset;
|
||||
}
|
||||
|
||||
public long getEndByteOffset() {
|
||||
return endByteOffset;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.datamodel.Content;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Event published when a data source is added to a case.
|
||||
*/
|
||||
public final class DataSourceAddedEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceAddedEvent.class.getName());
|
||||
private transient Content dataSource;
|
||||
private final UUID dataSourceId;
|
||||
|
||||
/**
|
||||
* Constructs an event published when a data source is added to a case.
|
||||
*
|
||||
* @param dataSource The data source that was added.
|
||||
* @param dataSourceId A unique identifier associated with the data source.
|
||||
* Used to pair this DataSourceAddedEvent with a
|
||||
* AddindDataSourceEvent.
|
||||
*/
|
||||
public DataSourceAddedEvent(Content dataSource, UUID dataSourceId) {
|
||||
/**
|
||||
* Putting the object id of the data source into newValue to allow for
|
||||
* lazy loading of the Content object. This bypasses the issues related
|
||||
* to the serialization and de-serialization of Content objects when the
|
||||
* event is published over a network.
|
||||
*/
|
||||
super(Case.Events.DATA_SOURCE_ADDED.toString(), null, dataSource.getId());
|
||||
this.dataSource = dataSource;
|
||||
this.dataSourceId = dataSourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data source that was added.
|
||||
*
|
||||
* @return The data source or null if there is an error retrieving the data
|
||||
* source.
|
||||
*/
|
||||
@Override
|
||||
public Object getNewValue() {
|
||||
/**
|
||||
* The dataSource field is set in the constructor, but it is transient
|
||||
* so it will become null when the event is serialized for publication
|
||||
* over a network. Doing a lazy load of the Content object bypasses the
|
||||
* issues related to the serialization and de-serialization of Content
|
||||
* objects and may also save database round trips from other nodes since
|
||||
* subscribers to this event are often not interested in the event data.
|
||||
*/
|
||||
if (null != dataSource) {
|
||||
return dataSource;
|
||||
}
|
||||
try {
|
||||
long id = (Long) super.getNewValue();
|
||||
dataSource = Case.getCurrentCase().getSleuthkitCase().getContentById(id);
|
||||
return dataSource;
|
||||
} catch (IllegalStateException | TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error doing lazy load for remote event", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data source that was added.
|
||||
*
|
||||
* @return The data source.
|
||||
*/
|
||||
public Content getDataSource() {
|
||||
return (Content) getNewValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the unique id for the data source used to pair this
|
||||
* DataSourceAddedEvent with a AddingDataSourceEvent.
|
||||
*
|
||||
* @return The unique id.
|
||||
*/
|
||||
public UUID getDataSourceId() {
|
||||
return dataSourceId;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.datamodel.Report;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Event published when a report is added to a case.
|
||||
*/
|
||||
public final class ReportAddedEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger logger = Logger.getLogger(DataSourceAddedEvent.class.getName());
|
||||
private transient Report report;
|
||||
|
||||
/**
|
||||
* Constructs an event published when a report is added to a case.
|
||||
*
|
||||
* @param report The data source that was added.
|
||||
*/
|
||||
public ReportAddedEvent(Report report) {
|
||||
/**
|
||||
* Putting the object id of the report into newValue to allow for lazy
|
||||
* loading of the Report object.
|
||||
*/
|
||||
super(Case.Events.REPORT_ADDED.toString(), null, report.getId());
|
||||
this.report = report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the data source that was added.
|
||||
*
|
||||
* @return The data source.
|
||||
*/
|
||||
@Override
|
||||
public Object getNewValue() {
|
||||
/**
|
||||
* The report field is set in the constructor, but it is transient so it
|
||||
* will become null when the event is serialized for publication over a
|
||||
* network. Doing a lazy load of the Report object may save database
|
||||
* round trips from other nodes since subscribers to this event are
|
||||
* often not interested in the event data.
|
||||
*/
|
||||
if (null != report) {
|
||||
return report;
|
||||
}
|
||||
try {
|
||||
long id = (Long) super.getNewValue();
|
||||
List<Report> reports = Case.getCurrentCase().getSleuthkitCase().getAllReports();
|
||||
for (Report thisReport : reports) {
|
||||
if (thisReport.getId() == id) {
|
||||
report = thisReport;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return report;
|
||||
} catch (IllegalStateException | TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error doing lazy load for remote event", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* Base Class for events that are fired when a Tag is added
|
||||
*/
|
||||
abstract class TagAddedEvent<T extends Tag> extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* The tag that was added. This will be lost during serialization and
|
||||
* re-loaded from the database in getNewValue()
|
||||
*/
|
||||
private transient T tag;
|
||||
|
||||
/**
|
||||
* The id of the tag that was added. This will bu used to re-load the
|
||||
* transient tag from the database.
|
||||
*/
|
||||
private final Long tagID;
|
||||
|
||||
TagAddedEvent(String propertyName, T addedTag) {
|
||||
super(propertyName, null, null);
|
||||
tag = addedTag;
|
||||
tagID = addedTag.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the id of the Tag that was added
|
||||
*
|
||||
* @return the id of the Tag that was added
|
||||
*/
|
||||
Long getTagID() {
|
||||
return tagID;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the Tag that was added
|
||||
*
|
||||
* @return the tTag
|
||||
*/
|
||||
public T getAddedTag() {
|
||||
return getNewValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T getNewValue() {
|
||||
/**
|
||||
* The tag field is set in the constructor, but it is transient so it
|
||||
* will become null when the event is serialized for publication over a
|
||||
* network. Doing a lazy load of the Tag object bypasses the issues
|
||||
* related to the serialization and de-serialization of Tag objects and
|
||||
* may also save database round trips from other nodes since subscribers
|
||||
* to this event are often not interested in the event data.
|
||||
*/
|
||||
if (null != tag) {
|
||||
return tag;
|
||||
}
|
||||
try {
|
||||
tag = getTagByID();
|
||||
return tag;
|
||||
} catch (IllegalStateException | TskCoreException ex) {
|
||||
Logger.getLogger(TagAddedEvent.class.getName()).log(Level.SEVERE, "Error doing lazy load for remote event", ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* implementors should override this to lookup the appropriate kind of tag
|
||||
* (Content/BlackBoardArtifact) during the lazy load of the transient tag
|
||||
* field
|
||||
*
|
||||
*
|
||||
* @return the Tag based on the saved tag id
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
abstract T getTagByID() throws IllegalStateException, TskCoreException;
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
import org.sleuthkit.datamodel.Tag;
|
||||
import org.sleuthkit.datamodel.TagName;
|
||||
|
||||
/**
|
||||
* Base Class for events that are fired when a Tag is deleted
|
||||
*/
|
||||
@Immutable
|
||||
abstract class TagDeletedEvent<T extends Tag> extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
TagDeletedEvent(String propertyName, DeletedTagInfo<T> deletedTagInfo) {
|
||||
super(propertyName, deletedTagInfo, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* get info about the Tag that was deleted.
|
||||
*
|
||||
* Since we don't serialize the deleted tag, and we can't look it up by id
|
||||
* after it is deleted, we send this info to represent it.
|
||||
*
|
||||
* @return info about the Tag that was deleted.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
abstract public DeletedTagInfo<T> getDeletedTagInfo();
|
||||
|
||||
/**
|
||||
* Base Class for info about a deleted tag. This is sent as the old value in
|
||||
* the event, since we are not serializing the Tag it self, and we can't
|
||||
* look it up by id, like we do for added tags, because it doesn't exist in
|
||||
* the db any more.
|
||||
*
|
||||
* @param <T> the subtype of Tag, BlackBoardArtifactTag or ContentTag
|
||||
*/
|
||||
@Immutable
|
||||
abstract static class DeletedTagInfo<T extends Tag> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String comment;
|
||||
private final long tagID;
|
||||
private final TagName name;
|
||||
|
||||
DeletedTagInfo(T deletedTag) {
|
||||
comment = deletedTag.getComment();
|
||||
tagID = deletedTag.getId();
|
||||
name = deletedTag.getName();
|
||||
}
|
||||
|
||||
abstract public long getContentID();
|
||||
|
||||
public String getComment() {
|
||||
return comment;
|
||||
}
|
||||
|
||||
public long getTagID() {
|
||||
return tagID;
|
||||
}
|
||||
|
||||
public TagName getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
@ -15,7 +15,7 @@ TagsManager.addContentTag.exception.beginByteOffsetOOR.msg=beginByteOffset \= {0
|
||||
TagsManager.addContentTag.exception.endByteOffsetOOR.msg=endByteOffset \= {0} out of content size range (0 - {1})
|
||||
TagsManager.addContentTag.exception.endLTbegin.msg=endByteOffset < beginByteOffset
|
||||
TagsManager.predefTagNames.bookmark.text=Bookmark
|
||||
TagsManager.addContentTag.noCaseWarning=Failed to add publish new content tag event. There is no case open.
|
||||
TagsManager.deleteContentTag.noCaseWarning=Failed to add publish content tag deleted event. There is no case open.
|
||||
TagsManager.addBlackboardArtifactTag.noCaseWarning=Failed to add publish new blackboard artifact tag event. There is no case open.
|
||||
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=Failed to add publish blackboard artifact tag deleted event. There is no case open.
|
||||
TagsManager.addContentTag.noCaseWarning=Failed to publish new content tag event. There is no case open.
|
||||
TagsManager.deleteContentTag.noCaseWarning=Failed to publish content tag deleted event. There is no case open.
|
||||
TagsManager.addBlackboardArtifactTag.noCaseWarning=Failed to publish new blackboard artifact tag event. There is no case open.
|
||||
TagsManager.deleteBlackboardArtifactTag.noCaseWarning=Failed to publish blackboard artifact tag deleted event. There is no case open.
|
||||
|
@ -272,7 +272,7 @@ public class TagsManager implements Closeable {
|
||||
tskCase.deleteContentTag(tag);
|
||||
try {
|
||||
Case.getCurrentCase().notifyContentTagDeleted(tag);
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (IllegalStateException e) {
|
||||
Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteContentTag.noCaseWarning"));
|
||||
}
|
||||
}
|
||||
@ -311,6 +311,24 @@ public class TagsManager implements Closeable {
|
||||
return tskCase.getContentTagsCountByTagName(tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a content tag by tag id.
|
||||
*
|
||||
* @param tagID The tag id of interest.
|
||||
*
|
||||
* @return the content tag with the specified tag id.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
public synchronized ContentTag getContentTagByTagID(long tagID) throws TskCoreException {
|
||||
// @@@ This is a work around to be removed when database access on the EDT is correctly synchronized.
|
||||
if (!tagNamesInitialized) {
|
||||
getExistingTagNames();
|
||||
}
|
||||
|
||||
return tskCase.getContentTagByID(tagID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets content tags by tag name.
|
||||
*
|
||||
@ -385,7 +403,7 @@ public class TagsManager implements Closeable {
|
||||
BlackboardArtifactTag addBlackboardArtifactTag = tskCase.addBlackboardArtifactTag(artifact, tagName, comment);
|
||||
try {
|
||||
Case.getCurrentCase().notifyBlackBoardArtifactTagAdded(addBlackboardArtifactTag);
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (IllegalStateException e) {
|
||||
Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.addBlackboardArtifactTag.noCaseWarning"));
|
||||
}
|
||||
return addBlackboardArtifactTag;
|
||||
@ -407,7 +425,7 @@ public class TagsManager implements Closeable {
|
||||
tskCase.deleteBlackboardArtifactTag(tag);
|
||||
try {
|
||||
Case.getCurrentCase().notifyBlackBoardArtifactTagDeleted(tag);
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (IllegalStateException e) {
|
||||
Logger.getLogger(TagsManager.class.getName()).log(Level.WARNING, NbBundle.getMessage(TagsManager.class, "TagsManager.deleteBlackboardArtifactTag.noCaseWarning"));
|
||||
}
|
||||
}
|
||||
@ -447,6 +465,24 @@ public class TagsManager implements Closeable {
|
||||
return tskCase.getBlackboardArtifactTagsCountByTagName(tagName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a blackboard artifact tag by tag id.
|
||||
*
|
||||
* @param tagID The tag id of interest.
|
||||
*
|
||||
* @return the blackboard artifact tag with the specified tag id.
|
||||
*
|
||||
* @throws TskCoreException
|
||||
*/
|
||||
public synchronized BlackboardArtifactTag getBlackboardArtifactTagByTagID(long tagID) throws TskCoreException {
|
||||
// @@@ This is a work around to be removed when database access on the EDT is correctly synchronized.
|
||||
if (!tagNamesInitialized) {
|
||||
getExistingTagNames();
|
||||
}
|
||||
|
||||
return tskCase.getBlackboardArtifactTagByID(tagID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets blackboard artifact tags by tag name.
|
||||
*
|
||||
|
@ -12,7 +12,7 @@ Metadata.tableRowTitle.hashLookupResults=Hash Lookup Results
|
||||
Metadata.tableRowTitle.internalid=Internal ID
|
||||
Metadata.tableRowTitle.localPath=Local Path
|
||||
Metadata.tableRowTitle.type=Type
|
||||
Metadata.title=Metadata
|
||||
Metadata.title=File Metadata
|
||||
Metadata.toolTip=Displays metadata about the file.
|
||||
Metadata.nodeText.nonFilePassedIn=Non-file passed in
|
||||
Metadata.nodeText.text=From The Sleuth Kit istat Tool\:
|
||||
|
@ -12,3 +12,15 @@ org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xm
|
||||
Services/AutoupdateType/org_sleuthkit_autopsy_core_update_center.settings=Autopsy Update Center
|
||||
Installer.errorInitJavafx.msg=Error initializing JavaFX.
|
||||
Installer.errorInitJavafx.details=\ Some features will not be available. Check that you have the right JRE installed (Oracle JRE > 1.7.10).
|
||||
ServicesMonitor.failedService.notify.title=Service Is Down
|
||||
ServicesMonitor.failedService.notify.msg=Connection to {0} is down
|
||||
ServicesMonitor.restoredService.notify.title=Service Is Up
|
||||
ServicesMonitor.restoredService.notify.msg=Connection to {0} is up
|
||||
ServicesMonitor.statusChange.notify.title=Service Status Update
|
||||
ServicesMonitor.statusChange.notify.msg=Status for {0} is {1}
|
||||
ServicesMonitor.nullServiceName.excepton.txt=Requested service name is null
|
||||
ServicesMonitor.unknownServiceName.excepton.txt=Requested service name {0} is unknown
|
||||
TextConverter.convert.exception.txt=Unable to convert text {0} to hex text
|
||||
TextConverter.convertFromHex.exception.txt=Unable to convert hex text to text
|
||||
ServicesMonitor.KeywordSearchNull=Cannot find Keyword Search service
|
||||
ServicesMonitor.InvalidPortNumber=Invalid port number.
|
@ -66,9 +66,10 @@ public class Installer extends ModuleInstall {
|
||||
//We should update this if we officially switch to a new version of CRT/compiler
|
||||
System.loadLibrary("msvcr100"); //NON-NLS
|
||||
System.loadLibrary("msvcp100"); //NON-NLS
|
||||
logger.log(Level.INFO, "MS CRT libraries loaded"); //NON-NLS
|
||||
System.loadLibrary("msvcr120"); //NON-NLS
|
||||
logger.log(Level.INFO, "MSVCR100 and MSVCP100 libraries loaded"); //NON-NLS
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading ms crt libraries, ", e); //NON-NLS
|
||||
logger.log(Level.SEVERE, "Error loading MSVCR100 and MSVCP100 libraries, ", e); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
@ -84,6 +85,34 @@ public class Installer extends ModuleInstall {
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading EWF library, ", e); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
System.loadLibrary("libeay32"); //NON-NLS
|
||||
logger.log(Level.INFO, "LIBEAY32 library loaded"); //NON-NLS
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading LIBEAY32 library, ", e); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
System.loadLibrary("ssleay32"); //NON-NLS
|
||||
logger.log(Level.INFO, "SSLEAY32 library loaded"); //NON-NLS
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading SSLEAY32 library, ", e); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
System.loadLibrary("libintl-8"); //NON-NLS
|
||||
logger.log(Level.INFO, "libintl-8 library loaded"); //NON-NLS
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading libintl-8 library, ", e); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
System.loadLibrary("libpq"); //NON-NLS
|
||||
logger.log(Level.INFO, "LIBPQ library loaded"); //NON-NLS
|
||||
} catch (UnsatisfiedLinkError e) {
|
||||
logger.log(Level.SEVERE, "Error loading LIBPQ library, ", e); //NON-NLS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
62
Core/src/org/sleuthkit/autopsy/core/RuntimeProperties.java
Normal file
62
Core/src/org/sleuthkit/autopsy/core/RuntimeProperties.java
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2015 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.core;
|
||||
|
||||
/**
|
||||
* Application properties that are set once at runtime and are not saved between
|
||||
* invocations of Autopsy.
|
||||
*/
|
||||
public class RuntimeProperties {
|
||||
|
||||
private static boolean coreComponentsActive = true;
|
||||
private static boolean coreComponentsActiveSet = false;
|
||||
|
||||
/**
|
||||
* Sets or unsets a flag indicating whether or not the core Autopsy UI
|
||||
* components and user interactions with those components via menus, message
|
||||
* boxes, NetBeans progress handles, etc., are enabled.
|
||||
* <p>
|
||||
* This flag exists as a mechanism to allow use of Autopsy as a platform
|
||||
* with the core Autopsy user interface disabled, until such time as the
|
||||
* user interface is made separable and optional.
|
||||
*
|
||||
* @param coreComponentsActive True or false.
|
||||
*/
|
||||
public static void setCoreComponentsActive(boolean coreComponentsActive) {
|
||||
if (!coreComponentsActiveSet) {
|
||||
RuntimeProperties.coreComponentsActive = coreComponentsActive;
|
||||
coreComponentsActiveSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a flag indicating whether or not the core Autopsy UI components and
|
||||
* user interactions with those components via menus, message boxes,
|
||||
* NetBeans progress handles, etc., are enabled.
|
||||
* <p>
|
||||
* This flag exists as a mechanism to allow use of Autopsy as a platform
|
||||
* with the core Autopsy user interface disabled, until such time as the
|
||||
* user interface is made separable and optional.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
public static boolean coreComponentsAreActive() {
|
||||
return coreComponentsActive;
|
||||
}
|
||||
}
|
411
Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java
Normal file
411
Core/src/org/sleuthkit/autopsy/core/ServicesMonitor.java
Normal file
@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2015 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.core;
|
||||
|
||||
import org.sleuthkit.autopsy.core.events.ServiceEvent;
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEventPublisher;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
|
||||
import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
|
||||
import org.sleuthkit.autopsy.events.MessageServiceException;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
* This class periodically checks availability of collaboration resources -
|
||||
* remote database, remote keyword search server, messaging service - and
|
||||
* reports status updates to the user in case of a gap in service.
|
||||
*/
|
||||
public class ServicesMonitor {
|
||||
|
||||
private AutopsyEventPublisher eventPublisher;
|
||||
private static final Logger logger = Logger.getLogger(ServicesMonitor.class.getName());
|
||||
private final ScheduledThreadPoolExecutor periodicTasksExecutor;
|
||||
|
||||
private static final String PERIODIC_TASK_THREAD_NAME = "services-monitor-periodic-task-%d";
|
||||
private static final int NUMBER_OF_PERIODIC_TASK_THREADS = 1;
|
||||
private static final long CRASH_DETECTION_INTERVAL_MINUTES = 2;
|
||||
|
||||
private static final Set<String> servicesList = Stream.of(ServicesMonitor.Service.values())
|
||||
.map(Service::toString)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
/**
|
||||
* The service monitor maintains a mapping of each service to it's last
|
||||
* status update.
|
||||
*/
|
||||
private final ConcurrentHashMap<String, String> statusByService;
|
||||
|
||||
/**
|
||||
* Call constructor on start-up so that the first check of services is done
|
||||
* as soon as possible.
|
||||
*/
|
||||
private static ServicesMonitor instance = new ServicesMonitor();
|
||||
|
||||
/**
|
||||
* List of services that are being monitored. The service names should be
|
||||
* representative of the service functionality and readable as they get
|
||||
* logged when service outage occurs.
|
||||
*/
|
||||
public enum Service {
|
||||
|
||||
/**
|
||||
* Property change event fired when remote case database service status
|
||||
* changes. New value is set to updated ServiceStatus, old value is
|
||||
* null.
|
||||
*/
|
||||
REMOTE_CASE_DATABASE("Multi-user case database service"),
|
||||
/**
|
||||
* Property change event fired when remote keyword search service status
|
||||
* changes. New value is set to updated ServiceStatus, old value is
|
||||
* null.
|
||||
*/
|
||||
REMOTE_KEYWORD_SEARCH("Multi-user keyword search service"),
|
||||
/**
|
||||
* Property change event fired when messaging service status changes.
|
||||
* New value is set to updated ServiceStatus, old value is null.
|
||||
*/
|
||||
MESSAGING("Messaging service");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private Service(String name) {
|
||||
this.displayName = name;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* List of possible service statuses.
|
||||
*/
|
||||
public enum ServiceStatus {
|
||||
|
||||
/**
|
||||
* Service is currently up.
|
||||
*/
|
||||
UP,
|
||||
/**
|
||||
* Service is currently down.
|
||||
*/
|
||||
DOWN
|
||||
};
|
||||
|
||||
public synchronized static ServicesMonitor getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ServicesMonitor();
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private ServicesMonitor() {
|
||||
|
||||
this.eventPublisher = new AutopsyEventPublisher();
|
||||
this.statusByService = new ConcurrentHashMap<>();
|
||||
|
||||
// First check is triggered immediately on current thread.
|
||||
checkAllServices();
|
||||
|
||||
/**
|
||||
* Start periodic task that check the availability of key collaboration
|
||||
* services.
|
||||
*/
|
||||
periodicTasksExecutor = new ScheduledThreadPoolExecutor(NUMBER_OF_PERIODIC_TASK_THREADS, new ThreadFactoryBuilder().setNameFormat(PERIODIC_TASK_THREAD_NAME).build());
|
||||
periodicTasksExecutor.scheduleAtFixedRate(new CrashDetectionTask(), CRASH_DETECTION_INTERVAL_MINUTES, CRASH_DETECTION_INTERVAL_MINUTES, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates service status and publishes the service status update if it is
|
||||
* different from previous status. Event is published locally. Logs status
|
||||
* changes.
|
||||
*
|
||||
* @param service Name of the service.
|
||||
* @param status Updated status for the service.
|
||||
* @param details Details of the event.
|
||||
*
|
||||
*/
|
||||
public void setServiceStatus(String service, String status, String details) {
|
||||
// if the status update is for an existing service who's status hasn't changed - do nothing.
|
||||
if (statusByService.containsKey(service) && status.equals(statusByService.get(service))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// new service or status has changed - identify service's display name
|
||||
String serviceDisplayName;
|
||||
try {
|
||||
serviceDisplayName = ServicesMonitor.Service.valueOf(service).getDisplayName();
|
||||
} catch (IllegalArgumentException ignore) {
|
||||
// custom service that is not listed in ServicesMonitor.Service enum. Use service name as display name.
|
||||
serviceDisplayName = service;
|
||||
}
|
||||
|
||||
if (status.equals(ServiceStatus.UP.toString())) {
|
||||
logger.log(Level.INFO, "Connection to {0} is up", serviceDisplayName); //NON-NLS
|
||||
MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.title"),
|
||||
NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.restoredService.notify.msg", serviceDisplayName));
|
||||
} else if (status.equals(ServiceStatus.DOWN.toString())) {
|
||||
logger.log(Level.SEVERE, "Failed to connect to {0}", serviceDisplayName); //NON-NLS
|
||||
MessageNotifyUtil.Notify.error(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.title"),
|
||||
NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.failedService.notify.msg", serviceDisplayName));
|
||||
} else {
|
||||
logger.log(Level.INFO, "Status for {0} is {1}", new Object[]{serviceDisplayName, status}); //NON-NLS
|
||||
MessageNotifyUtil.Notify.info(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.title"),
|
||||
NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.statusChange.notify.msg", new Object[]{serviceDisplayName, status}));
|
||||
}
|
||||
|
||||
// update and publish new status
|
||||
statusByService.put(service, status);
|
||||
eventPublisher.publishLocally(new ServiceEvent(service, status, details));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get last status update for a service.
|
||||
*
|
||||
* @param service Name of the service.
|
||||
*
|
||||
* @return ServiceStatus Status for the service.
|
||||
*
|
||||
* @throws ServicesMonitorException If service name is null or service
|
||||
* doesn't exist.
|
||||
*/
|
||||
public String getServiceStatus(String service) throws ServicesMonitorException {
|
||||
|
||||
if (service == null) {
|
||||
throw new ServicesMonitorException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.nullServiceName.excepton.txt"));
|
||||
}
|
||||
|
||||
// if request is for one of our "core" services - perform an on demand check
|
||||
// to make sure we have the latest status.
|
||||
if (servicesList.contains(service)) {
|
||||
checkServiceStatus(service);
|
||||
}
|
||||
|
||||
String status = statusByService.get(service);
|
||||
if (status == null) {
|
||||
// no such service
|
||||
throw new ServicesMonitorException(NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.unknownServiceName.excepton.txt", service));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs service availability status check.
|
||||
*
|
||||
* @param service Name of the service.
|
||||
*/
|
||||
private void checkServiceStatus(String service) {
|
||||
if (service.equals(Service.REMOTE_CASE_DATABASE.toString())) {
|
||||
checkDatabaseConnectionStatus();
|
||||
} else if (service.equals(Service.REMOTE_KEYWORD_SEARCH.toString())) {
|
||||
checkKeywordSearchServerConnectionStatus();
|
||||
} else if (service.equals(Service.MESSAGING.toString())) {
|
||||
checkMessagingServerConnectionStatus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs case database service availability status check.
|
||||
*/
|
||||
private void checkDatabaseConnectionStatus() {
|
||||
CaseDbConnectionInfo info;
|
||||
try {
|
||||
info = UserPreferences.getDatabaseConnectionInfo();
|
||||
} catch (UserPreferencesException ex) {
|
||||
logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS
|
||||
setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString(), "Error accessing case database connection info");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SleuthkitCase.tryConnect(info);
|
||||
setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.UP.toString(), "");
|
||||
} catch (TskCoreException ex) {
|
||||
setServiceStatus(Service.REMOTE_CASE_DATABASE.toString(), ServiceStatus.DOWN.toString(), ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs keyword search service availability status check.
|
||||
*/
|
||||
private void checkKeywordSearchServerConnectionStatus() {
|
||||
KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class);
|
||||
try {
|
||||
if (kwsService != null) {
|
||||
int port = Integer.parseUnsignedInt(UserPreferences.getIndexingServerPort());
|
||||
kwsService.tryConnect(UserPreferences.getIndexingServerHost(), port);
|
||||
setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.UP.toString(), "");
|
||||
} else {
|
||||
setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(),
|
||||
NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.KeywordSearchNull"));
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
String rootCause = NbBundle.getMessage(ServicesMonitor.class, "ServicesMonitor.InvalidPortNumber");
|
||||
logger.log(Level.SEVERE, "Unable to connect to messaging server: " + rootCause, ex); //NON-NLS
|
||||
setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), rootCause);
|
||||
} catch (KeywordSearchServiceException ex) {
|
||||
String rootCause = ex.getMessage();
|
||||
logger.log(Level.SEVERE, "Unable to connect to messaging server: " + rootCause, ex); //NON-NLS
|
||||
setServiceStatus(Service.REMOTE_KEYWORD_SEARCH.toString(), ServiceStatus.DOWN.toString(), rootCause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs messaging service availability status check.
|
||||
*/
|
||||
private void checkMessagingServerConnectionStatus() {
|
||||
MessageServiceConnectionInfo info;
|
||||
try {
|
||||
info = UserPreferences.getMessageServiceConnectionInfo();
|
||||
} catch (UserPreferencesException ex) {
|
||||
logger.log(Level.SEVERE, "Error accessing messaging service connection info", ex); //NON-NLS
|
||||
setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString(), "Error accessing messaging service connection info");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
info.tryConnect();
|
||||
setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.UP.toString(), "");
|
||||
} catch (MessageServiceException ex) {
|
||||
String rootCause = ex.getMessage();
|
||||
logger.log(Level.SEVERE, "Unable to connect to messaging server: " + rootCause, ex); //NON-NLS
|
||||
setServiceStatus(Service.MESSAGING.toString(), ServiceStatus.DOWN.toString(), rootCause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event subscriber to this publisher. Subscriber will be subscribed
|
||||
* to all events from this publisher.
|
||||
*
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public void addSubscriber(PropertyChangeListener subscriber) {
|
||||
eventPublisher.addSubscriber(servicesList, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event subscriber to this publisher.
|
||||
*
|
||||
* @param eventNames The events the subscriber is interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public void addSubscriber(Set<String> eventNames, PropertyChangeListener subscriber) {
|
||||
eventPublisher.addSubscriber(eventNames, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an event subscriber to this publisher.
|
||||
*
|
||||
* @param eventName The event the subscriber is interested in.
|
||||
* @param subscriber The subscriber to add.
|
||||
*/
|
||||
public void addSubscriber(String eventName, PropertyChangeListener subscriber) {
|
||||
eventPublisher.addSubscriber(eventName, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event subscriber from this publisher.
|
||||
*
|
||||
* @param eventNames The events the subscriber is no longer interested in.
|
||||
* @param subscriber The subscriber to remove.
|
||||
*/
|
||||
public void removeSubscriber(Set<String> eventNames, PropertyChangeListener subscriber) {
|
||||
eventPublisher.removeSubscriber(eventNames, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event subscriber from this publisher.
|
||||
*
|
||||
* @param eventName The event the subscriber is no longer interested in.
|
||||
* @param subscriber The subscriber to remove.
|
||||
*/
|
||||
public void removeSubscriber(String eventName, PropertyChangeListener subscriber) {
|
||||
eventPublisher.removeSubscriber(eventName, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an event subscriber to this publisher. Subscriber will be removed
|
||||
* from all event notifications from this publisher.
|
||||
*
|
||||
* @param subscriber The subscriber to remove.
|
||||
*/
|
||||
public void removeSubscriber(PropertyChangeListener subscriber) {
|
||||
eventPublisher.removeSubscriber(servicesList, subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies connectivity to all services.
|
||||
*/
|
||||
private void checkAllServices() {
|
||||
if (!UserPreferences.getIsMultiUserModeEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String service : servicesList) {
|
||||
checkServiceStatus(service);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Runnable task that periodically checks the availability of
|
||||
* collaboration resources (remote database, remote keyword search service,
|
||||
* message broker) and reports status to the user in case of a gap in
|
||||
* service.
|
||||
*/
|
||||
private final class CrashDetectionTask implements Runnable {
|
||||
|
||||
/**
|
||||
* Monitor the availability of collaboration resources
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
checkAllServices();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception thrown when service status query results in an error.
|
||||
*/
|
||||
public class ServicesMonitorException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ServicesMonitorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public ServicesMonitorException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,9 +18,20 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.core;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.prefs.BackingStoreException;
|
||||
import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
|
||||
import java.util.prefs.PreferenceChangeListener;
|
||||
import java.util.prefs.Preferences;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.PBEParameterSpec;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbPreferences;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.TskData.DbType;
|
||||
|
||||
/**
|
||||
* Provides convenient access to a Preferences node for user preferences with
|
||||
@ -34,11 +45,50 @@ public final class UserPreferences {
|
||||
public static final String HIDE_KNOWN_FILES_IN_VIEWS_TREE = "HideKnownFilesInViewsTree"; //NON-NLS
|
||||
public static final String DISPLAY_TIMES_IN_LOCAL_TIME = "DisplayTimesInLocalTime"; //NON-NLS
|
||||
public static final String NUMBER_OF_FILE_INGEST_THREADS = "NumberOfFileIngestThreads"; //NON-NLS
|
||||
public static final String IS_MULTI_USER_MODE_ENABLED = "IsMultiUserModeEnabled"; //NON-NLS
|
||||
public static final String EXTERNAL_DATABASE_HOSTNAME_OR_IP = "ExternalDatabaseHostnameOrIp"; //NON-NLS
|
||||
public static final String EXTERNAL_DATABASE_PORTNUMBER = "ExternalDatabasePortNumber"; //NON-NLS
|
||||
public static final String EXTERNAL_DATABASE_NAME = "ExternalDatabaseName"; //NON-NLS
|
||||
public static final String EXTERNAL_DATABASE_USER = "ExternalDatabaseUsername"; //NON-NLS
|
||||
public static final String EXTERNAL_DATABASE_PASSWORD = "ExternalDatabasePassword"; //NON-NLS
|
||||
public static final String EXTERNAL_DATABASE_TYPE = "ExternalDatabaseType"; //NON-NLS
|
||||
public static final String INDEXING_SERVER_HOST = "IndexingServerHost"; //NON-NLS
|
||||
public static final String INDEXING_SERVER_PORT = "IndexingServerPort"; //NON-NLS
|
||||
private static final String MESSAGE_SERVICE_PASSWORD = "MessageServicePassword"; //NON-NLS
|
||||
private static final String MESSAGE_SERVICE_USER = "MessageServiceUser"; //NON-NLS
|
||||
private static final String MESSAGE_SERVICE_HOST = "MessageServiceHost"; //NON-NLS
|
||||
private static final String MESSAGE_SERVICE_PORT = "MessageServicePort"; //NON-NLS
|
||||
public static final String PROCESS_TIME_OUT_ENABLED = "ProcessTimeOutEnabled"; //NON-NLS
|
||||
public static final String PROCESS_TIME_OUT_HOURS = "ProcessTimeOutHours"; //NON-NLS
|
||||
private static final int DEFAULT_PROCESS_TIMEOUT_HR = 60;
|
||||
private static final String DEFAULT_PORT_STRING = "61616";
|
||||
private static final int DEFAULT_PORT_INT = 61616;
|
||||
|
||||
// Prevent instantiation.
|
||||
private UserPreferences() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reload all preferences from disk. This is only needed if the preferences
|
||||
* file is being directly modified on disk while Autopsy is running.
|
||||
*
|
||||
* @throws BackingStoreException
|
||||
*/
|
||||
public static void reloadFromStorage() throws BackingStoreException {
|
||||
preferences.sync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current preferences to storage. This is only needed if the
|
||||
* preferences files are going to be copied to another location while
|
||||
* Autopsy is running.
|
||||
*
|
||||
* @throws BackingStoreException
|
||||
*/
|
||||
public static void saveToStorage() throws BackingStoreException {
|
||||
preferences.flush();
|
||||
}
|
||||
|
||||
public static void addChangeListener(PreferenceChangeListener listener) {
|
||||
preferences.addPreferenceChangeListener(listener);
|
||||
}
|
||||
@ -87,4 +137,209 @@ public final class UserPreferences {
|
||||
preferences.putInt(NUMBER_OF_FILE_INGEST_THREADS, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads persisted case database connection info.
|
||||
* @return An object encapsulating the database connection info.
|
||||
* @throws org.sleuthkit.autopsy.core.UserPreferencesException
|
||||
*/
|
||||
public static CaseDbConnectionInfo getDatabaseConnectionInfo() throws UserPreferencesException {
|
||||
DbType dbType;
|
||||
try {
|
||||
dbType = DbType.valueOf(preferences.get(EXTERNAL_DATABASE_TYPE, "POSTGRESQL"));
|
||||
} catch (Exception ex) {
|
||||
dbType = DbType.SQLITE;
|
||||
}
|
||||
return new CaseDbConnectionInfo(
|
||||
preferences.get(EXTERNAL_DATABASE_HOSTNAME_OR_IP, ""),
|
||||
preferences.get(EXTERNAL_DATABASE_PORTNUMBER, "5432"),
|
||||
preferences.get(EXTERNAL_DATABASE_USER, ""),
|
||||
TextConverter.convertHexTextToText(preferences.get(EXTERNAL_DATABASE_PASSWORD, "")),
|
||||
dbType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists case database connection info.
|
||||
*
|
||||
* @param connectionInfo An object encapsulating the database connection
|
||||
* info.
|
||||
* @throws org.sleuthkit.autopsy.core.UserPreferencesException
|
||||
*/
|
||||
public static void setDatabaseConnectionInfo(CaseDbConnectionInfo connectionInfo) throws UserPreferencesException {
|
||||
preferences.put(EXTERNAL_DATABASE_HOSTNAME_OR_IP, connectionInfo.getHost());
|
||||
preferences.put(EXTERNAL_DATABASE_PORTNUMBER, connectionInfo.getPort());
|
||||
preferences.put(EXTERNAL_DATABASE_USER, connectionInfo.getUserName());
|
||||
preferences.put(EXTERNAL_DATABASE_PASSWORD, TextConverter.convertTextToHexText(connectionInfo.getPassword()));
|
||||
preferences.put(EXTERNAL_DATABASE_TYPE, connectionInfo.getDbType().toString());
|
||||
}
|
||||
|
||||
public static void setIsMultiUserModeEnabled(boolean enabled) {
|
||||
preferences.putBoolean(IS_MULTI_USER_MODE_ENABLED, enabled);
|
||||
}
|
||||
|
||||
public static boolean getIsMultiUserModeEnabled() {
|
||||
return preferences.getBoolean(IS_MULTI_USER_MODE_ENABLED, false);
|
||||
}
|
||||
|
||||
public static String getIndexingServerHost() {
|
||||
return preferences.get(INDEXING_SERVER_HOST, "");
|
||||
}
|
||||
|
||||
public static void setIndexingServerHost(String hostName) {
|
||||
preferences.put(INDEXING_SERVER_HOST, hostName);
|
||||
}
|
||||
|
||||
public static String getIndexingServerPort() {
|
||||
return preferences.get(INDEXING_SERVER_PORT, "8983");
|
||||
}
|
||||
|
||||
public static void setIndexingServerPort(int port) {
|
||||
preferences.putInt(INDEXING_SERVER_PORT, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists message service connection info.
|
||||
*
|
||||
* @param info An object encapsulating the message service info.
|
||||
* @throws org.sleuthkit.autopsy.core.UserPreferencesException
|
||||
*/
|
||||
public static void setMessageServiceConnectionInfo(MessageServiceConnectionInfo info) throws UserPreferencesException {
|
||||
preferences.put(MESSAGE_SERVICE_HOST, info.getHost());
|
||||
preferences.put(MESSAGE_SERVICE_PORT, Integer.toString(info.getPort()));
|
||||
preferences.put(MESSAGE_SERVICE_USER, info.getUserName());
|
||||
preferences.put(MESSAGE_SERVICE_PASSWORD, TextConverter.convertTextToHexText(info.getPassword()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads persisted message service connection info.
|
||||
*
|
||||
* @return An object encapsulating the message service info.
|
||||
* @throws org.sleuthkit.autopsy.core.UserPreferencesException
|
||||
*/
|
||||
public static MessageServiceConnectionInfo getMessageServiceConnectionInfo() throws UserPreferencesException {
|
||||
int port;
|
||||
try {
|
||||
port = Integer.parseInt(preferences.get(MESSAGE_SERVICE_PORT, DEFAULT_PORT_STRING));
|
||||
} catch (NumberFormatException ex) {
|
||||
// if there is an error parsing the port number, use the default port number
|
||||
port = DEFAULT_PORT_INT;
|
||||
}
|
||||
|
||||
return new MessageServiceConnectionInfo(
|
||||
preferences.get(MESSAGE_SERVICE_HOST, ""),
|
||||
port,
|
||||
preferences.get(MESSAGE_SERVICE_USER, ""),
|
||||
TextConverter.convertHexTextToText(preferences.get(MESSAGE_SERVICE_PASSWORD, "")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads persisted process time out value.
|
||||
*
|
||||
* @return int Process time out value (hours).
|
||||
*/
|
||||
public static int getProcessTimeOutHrs() {
|
||||
int timeOut = preferences.getInt(PROCESS_TIME_OUT_HOURS, DEFAULT_PROCESS_TIMEOUT_HR);
|
||||
if (timeOut < 0) {
|
||||
timeOut = 0;
|
||||
}
|
||||
return timeOut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores persisted process time out value.
|
||||
*
|
||||
* @param value Persisted process time out value (hours).
|
||||
*/
|
||||
public static void setProcessTimeOutHrs(int value) {
|
||||
if (value < 0) {
|
||||
value = 0;
|
||||
}
|
||||
preferences.putInt(PROCESS_TIME_OUT_HOURS, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads persisted setting of whether process time out functionality is
|
||||
* enabled.
|
||||
*
|
||||
* @return boolean True if process time out is functionality enabled, false
|
||||
* otherwise.
|
||||
*/
|
||||
public static boolean getIsTimeOutEnabled() {
|
||||
boolean enabled = preferences.getBoolean(PROCESS_TIME_OUT_ENABLED, false);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores persisted setting of whether process time out functionality is
|
||||
* enabled.
|
||||
*
|
||||
* @param enabled Persisted setting of whether process time out
|
||||
* functionality is enabled.
|
||||
*/
|
||||
public static void setIsTimeOutEnabled(boolean enabled) {
|
||||
preferences.putBoolean(PROCESS_TIME_OUT_ENABLED, enabled);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Provides ability to convert text to hex text.
|
||||
*/
|
||||
static final class TextConverter {
|
||||
|
||||
private static final char[] TMP = "hgleri21auty84fwe".toCharArray();
|
||||
private static final byte[] SALT = {
|
||||
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,
|
||||
(byte) 0xde, (byte) 0x33, (byte) 0x10, (byte) 0x12,};
|
||||
|
||||
/**
|
||||
* Convert text to hex text.
|
||||
*
|
||||
* @param property Input text string.
|
||||
*
|
||||
* @return Converted hex string.
|
||||
*
|
||||
* @throws org.sleuthkit.autopsy.core.UserPreferencesException
|
||||
*/
|
||||
static String convertTextToHexText(String property) throws UserPreferencesException {
|
||||
try {
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
|
||||
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP));
|
||||
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
|
||||
pbeCipher.init(Cipher.ENCRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
|
||||
return base64Encode(pbeCipher.doFinal(property.getBytes("UTF-8")));
|
||||
} catch (Exception ex) {
|
||||
throw new UserPreferencesException(
|
||||
NbBundle.getMessage(TextConverter.class, "TextConverter.convert.exception.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
private static String base64Encode(byte[] bytes) {
|
||||
return Base64.getEncoder().encodeToString(bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex text back to text.
|
||||
*
|
||||
* @param property Input hex text string.
|
||||
*
|
||||
* @return Converted text string.
|
||||
*
|
||||
* @throws org.sleuthkit.autopsy.core.UserPreferencesException
|
||||
*/
|
||||
static String convertHexTextToText(String property) throws UserPreferencesException {
|
||||
try {
|
||||
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBEWithMD5AndDES");
|
||||
SecretKey key = keyFactory.generateSecret(new PBEKeySpec(TMP));
|
||||
Cipher pbeCipher = Cipher.getInstance("PBEWithMD5AndDES");
|
||||
pbeCipher.init(Cipher.DECRYPT_MODE, key, new PBEParameterSpec(SALT, 20));
|
||||
return new String(pbeCipher.doFinal(base64Decode(property)), "UTF-8");
|
||||
} catch (Exception ex) {
|
||||
throw new UserPreferencesException(
|
||||
NbBundle.getMessage(TextConverter.class, "TextConverter.convertFromHex.exception.txt"));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] base64Decode(String property) {
|
||||
return Base64.getDecoder().decode(property);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,19 +16,20 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.events;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.datamodel.ContentTag;
|
||||
package org.sleuthkit.autopsy.core;
|
||||
|
||||
/**
|
||||
* An event that is fired when a ContentTag is deleted.
|
||||
* Exception thrown when text conversion (such as from text to hex text or vice versa) resulted in
|
||||
* an error
|
||||
*/
|
||||
@Immutable
|
||||
public class ContentTagDeletedEvent extends TagDeletedEvent<ContentTag> {
|
||||
public class UserPreferencesException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public ContentTagDeletedEvent(ContentTag deletedTag) {
|
||||
super(Case.Events.CONTENT_TAG_DELETED.toString(), deletedTag);
|
||||
public UserPreferencesException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UserPreferencesException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
}
|
49
Core/src/org/sleuthkit/autopsy/core/events/ServiceEvent.java
Normal file
49
Core/src/org/sleuthkit/autopsy/core/events/ServiceEvent.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2015 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.core.events;
|
||||
|
||||
import java.io.Serializable;
|
||||
import org.sleuthkit.autopsy.events.AutopsyEvent;
|
||||
|
||||
/**
|
||||
* A class for events to be published to registered subscribers of Service
|
||||
* Monitor on this Autopsy node. The class extends PropertyChangeEvent (via
|
||||
* AutopsyEvent) to integrate with legacy use of JavaBeans PropertyChangeEvents
|
||||
* and PropertyChangeListeners as an application event system, and implements
|
||||
* Serializable to allow it to be published over a network in serialized form.
|
||||
*/
|
||||
public final class ServiceEvent extends AutopsyEvent implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final String details;
|
||||
|
||||
public ServiceEvent(String serviceName, String status, String details) {
|
||||
super(serviceName, null, status);
|
||||
this.details = details;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets details string passed as input to ServiceEvent constructor.
|
||||
*
|
||||
* @return String Details of the event.
|
||||
*/
|
||||
public String getDetails() {
|
||||
return details;
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@
|
||||
<folder name="Java.instance_hidden"/>
|
||||
<folder name="Advanced.instance_hidden"/> <!-- Miscellaneous -->
|
||||
<file name="org-sleuthkit-autopsy-corecomponents-AutopsyOptionsPanelController.instance">
|
||||
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/corecomponents/checkbox.png"/>
|
||||
<attr name="iconBase" stringvalue="org/sleuthkit/autopsy/corecomponents/checkbox32.png"/>
|
||||
<attr name="instanceCreate" methodvalue="org.netbeans.spi.options.OptionsCategory.createCategory"/>
|
||||
<attr name="keywordsCategory" stringvalue="General"/>
|
||||
<attr name="position" intvalue="1"/>
|
||||
@ -44,7 +44,6 @@
|
||||
<file name="org-sleuthkit-autopsy-casemodule-CaseNewAction.instance">
|
||||
<attr name="delegate" newvalue="org.sleuthkit.autopsy.casemodule.CaseNewAction"/>
|
||||
<attr name="displayName" bundlevalue="org.sleuthkit.autopsy.casemodule.Bundle#CTL_CaseNewAction"/>
|
||||
<attr name="instanceCreate" methodvalue="org.openide.awt.Actions.alwaysEnabled"/>
|
||||
<attr name="noIconInMenu" boolvalue="false"/>
|
||||
</file>
|
||||
<file name="org-sleuthkit-autopsy-casemodule-CasePropertiesAction.instance"/>
|
||||
@ -203,6 +202,13 @@
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-filesearch-FileSearchAction.instance"/>
|
||||
<attr name="position" intvalue="200"/>
|
||||
</file>
|
||||
<folder name="RunIngestModules">
|
||||
<attr name="position" intvalue="201"/>
|
||||
<attr name="SystemFileSystem.localizingBundle" stringvalue="org.sleuthkit.autopsy.ingest.Bundle"/>
|
||||
<file name="org-sleuthkit-autopsy-ingest-RunIngestAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-ingest-RunIngestAction.instance"/>
|
||||
</file>
|
||||
</folder>
|
||||
<file name="org-sleuthkit-autopsy-report-ReportWizardAction.shadow">
|
||||
<attr name="originalFile" stringvalue="Actions/Tools/org-sleuthkit-autopsy-report-ReportWizardAction.instance"/>
|
||||
<attr name="position" intvalue="100"/>
|
||||
@ -215,6 +221,8 @@
|
||||
<file name="Separator3.instance_hidden"/>-->
|
||||
</folder>
|
||||
<folder name="Window">
|
||||
<file name="GroupsMenuAction.shadow_hidden"/>
|
||||
<file name="Tools_hidden"/>
|
||||
<file name="Web_hidden"/>
|
||||
<file name="org-netbeans-modules-favorites-View.shadow_hidden"/>
|
||||
<file name="CloneDocumentAction.shadow_hidden"/>
|
||||
@ -227,6 +235,7 @@
|
||||
<file name="ViewFavoritesTabAction.shadow_hidden"/>
|
||||
<file name="org-netbeans-core-windows-actions-ResetWindowsAction.shadow_hidden"/>
|
||||
<file name="testAction.shadow_hidden"/>
|
||||
<file name="org-netbeans-core-io-ui-IOWindowAction.shadow_hidden"/>
|
||||
<file name="org-sleuthkit-autopsy-menuactions-DataResultMenu-separatoBefore.instance">
|
||||
<attr name="instanceClass" stringvalue="javax.swing.JSeparator"/>
|
||||
<attr name="position" intvalue="75"/>
|
||||
|
@ -26,7 +26,7 @@ import java.net.URL;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import javax.swing.Icon;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JPanel;
|
||||
|
@ -6,8 +6,6 @@
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="buttonGroup3">
|
||||
</Component>
|
||||
<Component class="javax.swing.ButtonGroup" name="buttonGroupProcTimeOut">
|
||||
</Component>
|
||||
</NonVisualComponents>
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
@ -58,6 +56,20 @@
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Group type="102" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
|
||||
<Component id="jCheckBoxEnableProcTimeout" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jFormattedTextFieldProcTimeOutHrs" min="-2" pref="27" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="jLabelProcessTimeOutUnits" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="jLabelSetProcessTimeOut" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
@ -89,7 +101,17 @@
|
||||
<Component id="numberOfFileIngestThreadsComboBox" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="restartRequiredLabel" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace pref="155" max="32767" attributes="0"/>
|
||||
<EmptySpace type="unrelated" max="-2" attributes="0"/>
|
||||
<Component id="jLabelSetProcessTimeOut" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="jCheckBoxEnableProcTimeout" min="-2" max="-2" attributes="0"/>
|
||||
<Group type="103" alignment="0" groupAlignment="3" attributes="0">
|
||||
<Component id="jFormattedTextFieldProcTimeOutHrs" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="jLabelProcessTimeOutUnits" alignment="3" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace pref="103" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
@ -205,5 +227,39 @@
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabelSetProcessTimeOut">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelSetProcessTimeOut.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JCheckBox" name="jCheckBoxEnableProcTimeout">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jCheckBoxEnableProcTimeoutActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="jLabelProcessTimeOutUnits">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JFormattedTextField" name="jFormattedTextFieldProcTimeOutHrs">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<AuxValues>
|
||||
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new JFormattedTextField(NumberFormat.getIntegerInstance());"/>
|
||||
</AuxValues>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Form>
|
||||
|
@ -18,7 +18,9 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JFormattedTextField;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
|
||||
@ -81,6 +83,19 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
useLocalTimeRB.setSelected(useLocalTime);
|
||||
useGMTTimeRB.setSelected(!useLocalTime);
|
||||
numberOfFileIngestThreadsComboBox.setSelectedItem(UserPreferences.numberOfFileIngestThreads());
|
||||
if (UserPreferences.getIsTimeOutEnabled()) {
|
||||
// user specified time out
|
||||
jCheckBoxEnableProcTimeout.setSelected(true);
|
||||
jFormattedTextFieldProcTimeOutHrs.setEditable(true);
|
||||
int timeOutHrs = UserPreferences.getProcessTimeOutHrs();
|
||||
jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs);
|
||||
} else {
|
||||
// never time out
|
||||
jCheckBoxEnableProcTimeout.setSelected(false);
|
||||
jFormattedTextFieldProcTimeOutHrs.setEditable(false);
|
||||
int timeOutHrs = UserPreferences.getProcessTimeOutHrs();
|
||||
jFormattedTextFieldProcTimeOutHrs.setValue((long) timeOutHrs);
|
||||
}
|
||||
}
|
||||
|
||||
void store() {
|
||||
@ -89,6 +104,13 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
UserPreferences.setHideKnownFilesInViewsTree(viewsHideKnownCB.isSelected());
|
||||
UserPreferences.setDisplayTimesInLocalTime(useLocalTimeRB.isSelected());
|
||||
UserPreferences.setNumberOfFileIngestThreads((Integer) numberOfFileIngestThreadsComboBox.getSelectedItem());
|
||||
|
||||
UserPreferences.setIsTimeOutEnabled(jCheckBoxEnableProcTimeout.isSelected());
|
||||
if (jCheckBoxEnableProcTimeout.isSelected()) {
|
||||
// only store time out if it is enabled
|
||||
long timeOutHrs = (long) jFormattedTextFieldProcTimeOutHrs.getValue();
|
||||
UserPreferences.setProcessTimeOutHrs((int) timeOutHrs);
|
||||
}
|
||||
}
|
||||
|
||||
boolean valid() {
|
||||
@ -105,7 +127,6 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
|
||||
buttonGroup1 = new javax.swing.ButtonGroup();
|
||||
buttonGroup3 = new javax.swing.ButtonGroup();
|
||||
buttonGroupProcTimeOut = new javax.swing.ButtonGroup();
|
||||
useBestViewerRB = new javax.swing.JRadioButton();
|
||||
keepCurrentViewerRB = new javax.swing.JRadioButton();
|
||||
jLabelSelectFile = new javax.swing.JLabel();
|
||||
@ -118,6 +139,10 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
jLabelNumThreads = new javax.swing.JLabel();
|
||||
numberOfFileIngestThreadsComboBox = new javax.swing.JComboBox<Integer>();
|
||||
restartRequiredLabel = new javax.swing.JLabel();
|
||||
jLabelSetProcessTimeOut = new javax.swing.JLabel();
|
||||
jCheckBoxEnableProcTimeout = new javax.swing.JCheckBox();
|
||||
jLabelProcessTimeOutUnits = new javax.swing.JLabel();
|
||||
jFormattedTextFieldProcTimeOutHrs = new JFormattedTextField(NumberFormat.getIntegerInstance());
|
||||
|
||||
buttonGroup1.add(useBestViewerRB);
|
||||
useBestViewerRB.setSelected(true);
|
||||
@ -150,6 +175,19 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
restartRequiredLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/corecomponents/warning16.png"))); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(restartRequiredLabel, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.restartRequiredLabel.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabelSetProcessTimeOut, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelSetProcessTimeOut.text")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jCheckBoxEnableProcTimeout, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text")); // NOI18N
|
||||
jCheckBoxEnableProcTimeout.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
jCheckBoxEnableProcTimeoutActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(jLabelProcessTimeOutUnits, org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text")); // NOI18N
|
||||
|
||||
jFormattedTextFieldProcTimeOutHrs.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
@ -180,7 +218,18 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
.addComponent(useGMTTimeRB)))
|
||||
.addComponent(jLabelSelectFile)
|
||||
.addComponent(jLabelNumThreads))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))))
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(layout.createSequentialGroup()
|
||||
.addGap(10, 10, 10)
|
||||
.addComponent(jCheckBoxEnableProcTimeout)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, 27, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(jLabelProcessTimeOutUnits))
|
||||
.addComponent(jLabelSetProcessTimeOut))
|
||||
.addGap(0, 0, Short.MAX_VALUE))))
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
@ -208,18 +257,33 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(numberOfFileIngestThreadsComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(restartRequiredLabel))
|
||||
.addContainerGap(155, Short.MAX_VALUE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
|
||||
.addComponent(jLabelSetProcessTimeOut)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(jCheckBoxEnableProcTimeout)
|
||||
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
|
||||
.addComponent(jFormattedTextFieldProcTimeOutHrs, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(jLabelProcessTimeOutUnits)))
|
||||
.addContainerGap(103, Short.MAX_VALUE))
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
private void jCheckBoxEnableProcTimeoutActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jCheckBoxEnableProcTimeoutActionPerformed
|
||||
jFormattedTextFieldProcTimeOutHrs.setEditable(jCheckBoxEnableProcTimeout.isSelected());
|
||||
}//GEN-LAST:event_jCheckBoxEnableProcTimeoutActionPerformed
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.ButtonGroup buttonGroup1;
|
||||
private javax.swing.ButtonGroup buttonGroup3;
|
||||
private javax.swing.ButtonGroup buttonGroupProcTimeOut;
|
||||
private javax.swing.JCheckBox dataSourcesHideKnownCB;
|
||||
private javax.swing.JCheckBox jCheckBoxEnableProcTimeout;
|
||||
private javax.swing.JFormattedTextField jFormattedTextFieldProcTimeOutHrs;
|
||||
private javax.swing.JLabel jLabelHideKnownFiles;
|
||||
private javax.swing.JLabel jLabelNumThreads;
|
||||
private javax.swing.JLabel jLabelProcessTimeOutUnits;
|
||||
private javax.swing.JLabel jLabelSelectFile;
|
||||
private javax.swing.JLabel jLabelSetProcessTimeOut;
|
||||
private javax.swing.JLabel jLabelTimeDisplay;
|
||||
private javax.swing.JRadioButton keepCurrentViewerRB;
|
||||
private javax.swing.JComboBox<Integer> numberOfFileIngestThreadsComboBox;
|
||||
|
@ -30,7 +30,7 @@ import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_General",
|
||||
iconBase = "org/sleuthkit/autopsy/corecomponents/checkbox.png",
|
||||
iconBase = "org/sleuthkit/autopsy/corecomponents/checkbox32.png",
|
||||
position = 1,
|
||||
keywords = "#OptionsCategory_Keywords_General",
|
||||
keywordsCategory = "General")
|
||||
|
@ -147,7 +147,52 @@ AutopsyOptionsPanel.jLabelNumThreads.text=Number of threads to use for file inge
|
||||
FXVideoPanel.progress.bufferingCancelled=media buffering was canceled
|
||||
FXVideoPanel.progress.bufferingInterrupted=media buffering was interrupted
|
||||
FXVideoPanel.progress.errorWritingVideoToDisk=Error writing video to disk
|
||||
OptionsCategory_Name_Multi_User_Settings=Multi-user
|
||||
OptionsCategory_Keywords_Multi_User_Options=Multi-user Options
|
||||
MultiUserSettingsPanel.lbSolrSettings.text=Solr Settings
|
||||
MultiUserSettingsPanel.cbEnableMultiUser.text=Enable Multi-user cases
|
||||
MultiUserSettingsPanel.lbDatabaseSettings.text=Database Settings
|
||||
MultiUserSettingsPanel.validationErrMsg.incomplete=Fill in all values
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort=Invalid database port number
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort=Invalid message service port number
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort=Invalid Solr server port number
|
||||
MultiUserSettingsPanel.validationErrMsg.invalidMessgeServiceURI=Message service host and/or port not valid
|
||||
AutopsyOptionsPanel.jCheckBoxEnableProcTimeout.text=
|
||||
AutopsyOptionsPanel.jFormattedTextFieldProcTimeOutHrs.text=60
|
||||
AutopsyOptionsPanel.jLabelProcessTimeOutUnits.text=hour(s)
|
||||
AutopsyOptionsPanel.jLabelSetProcessTimeOut.text=Enable timeout to allow modules to automatically terminate after a set amount of time:
|
||||
DataContentViewerHex.goToOffsetLabel.text=Jump to Offset
|
||||
DataContentViewerHex.goToOffsetTextField.text=
|
||||
DataContentViewerHex.goToOffsetTextField.msgDlg=Invalid Offset: {0}
|
||||
DataContentViewerHex.setDataView.invalidOffset.negativeOffsetValue=Cannot jump to the resultant offset
|
||||
MultiUserSettingsPanel.tbOops.text=
|
||||
MultiUserSettingsPanel.lbTestDatabase.text=
|
||||
MultiUserSettingsPanel.bnTestDatabase.text=Test
|
||||
MultiUserSettingsPanel.tbDbHostname.toolTipText=Hostname or IP Address
|
||||
MultiUserSettingsPanel.tbDbHostname.text=
|
||||
MultiUserSettingsPanel.tbDbPort.toolTipText=Port Number
|
||||
MultiUserSettingsPanel.tbDbPort.text=
|
||||
MultiUserSettingsPanel.tbDbUsername.toolTipText=User Name
|
||||
MultiUserSettingsPanel.tbDbUsername.text=
|
||||
MultiUserSettingsPanel.tbDbPassword.toolTipText=Password
|
||||
MultiUserSettingsPanel.tbDbPassword.text=
|
||||
MultiUserSettingsPanel.lbTestSolr.text=
|
||||
MultiUserSettingsPanel.bnTestSolr.text=Test
|
||||
MultiUserSettingsPanel.tbSolrHostname.toolTipText=Hostname or IP Address
|
||||
MultiUserSettingsPanel.tbSolrPort.toolTipText=Port Number
|
||||
MultiUserSettingsPanel.lbTestMessageService.text=
|
||||
MultiUserSettingsPanel.bnTestMessageService.text=Test
|
||||
MultiUserSettingsPanel.lbMessageServiceSettings.text=ActiveMQ Message Service Settings
|
||||
MultiUserSettingsPanel.tbMsgPort.toolTipText=Port Number
|
||||
MultiUserSettingsPanel.tbMsgPort.text=
|
||||
MultiUserSettingsPanel.tbMsgUsername.toolTipText=User Name
|
||||
MultiUserSettingsPanel.tbMsgUsername.text=
|
||||
MultiUserSettingsPanel.tbMsgPassword.toolTipText=Password
|
||||
MultiUserSettingsPanel.tbMsgPassword.text=
|
||||
MultiUserSettingsPanel.tbMsgHostname.toolTipText=Hostname or IP Address
|
||||
MultiUserSettingsPanel.tbMsgHostname.text=
|
||||
MultiUserSettingsPanel.lbTestMessageWarning.text=
|
||||
MultiUserSettingsPanel.lbTestSolrWarning.text=
|
||||
MultiUserSettingsPanel.lbTestDbWarning.text=
|
||||
MultiUserSettingsPanel.KeywordSearchNull=Cannot find Keyword Search service
|
||||
MultiUserSettingsPanel.InvalidPortNumber=Invalid port number.
|
@ -171,7 +171,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
||||
}
|
||||
|
||||
/**
|
||||
* is the given file a video we can display?
|
||||
* Is the given file a video we can display?
|
||||
*
|
||||
* @param file
|
||||
*
|
||||
@ -185,14 +185,13 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
|
||||
}
|
||||
|
||||
/**
|
||||
* is the given file an image that we can display?
|
||||
* Is the given file an image that we can display?
|
||||
*
|
||||
* @param file
|
||||
*
|
||||
* @return True if an image file that can be displayed
|
||||
*/
|
||||
private boolean isImageSupported(AbstractFile file) {
|
||||
|
||||
if (null == file || file.getSize() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
@ -45,11 +45,7 @@
|
||||
</Group>
|
||||
</Group>
|
||||
</Group>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
<Component id="iconView" pref="563" max="32767" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="iconView" alignment="0" pref="563" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
|
@ -578,6 +578,5 @@ final class DataResultViewerThumbnail extends AbstractDataResultViewer {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 Basis Technology Corp.
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -69,25 +69,26 @@ public class Installer extends ModuleInstall {
|
||||
/*
|
||||
* Open the passed in case, if an aut file was double clicked.
|
||||
*/
|
||||
WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
WindowManager.getDefault().invokeWhenUIReady(() -> {
|
||||
Collection<? extends OptionProcessor> processors = Lookup.getDefault().lookupAll(OptionProcessor.class);
|
||||
for (OptionProcessor processor : processors) {
|
||||
if (processor instanceof OpenFromArguments) {
|
||||
OpenFromArguments argsProcessor = (OpenFromArguments) processor;
|
||||
String caseFile = argsProcessor.getDefaultArg();
|
||||
final String caseFile = argsProcessor.getDefaultArg();
|
||||
if (caseFile != null && !caseFile.equals("") && caseFile.endsWith(".aut") && new File(caseFile).exists()) { //NON-NLS
|
||||
new Thread(() -> {
|
||||
// Create case.
|
||||
try {
|
||||
Case.open(caseFile);
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
} catch (Exception ex) {
|
||||
logger.log(Level.SEVERE, "Error opening case: ", ex); //NON-NLS
|
||||
}
|
||||
}).start();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
Case.invokeStartupDialog(); // bring up the startup dialog
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
@ -95,18 +96,19 @@ public class Installer extends ModuleInstall {
|
||||
@Override
|
||||
public void uninstalled() {
|
||||
super.uninstalled();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
if (Case.isCaseOpen()) {
|
||||
Case.getCurrentCase().closeCase();
|
||||
}
|
||||
} catch (CaseActionException ex) {
|
||||
logger.log(Level.WARNING, "Error closing case. ", ex); //NON-NLS
|
||||
} catch (CaseActionException | IllegalStateException unused) {
|
||||
// Exception already logged. Shutting down, no need to do popup.
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void setupLAF() {
|
||||
@ -157,8 +159,8 @@ public class Installer extends ModuleInstall {
|
||||
}
|
||||
|
||||
// Overwrite the Metal menu item keys to use the Aqua versions
|
||||
for (Map.Entry<Object, Object> entry : uiEntries.entrySet()) {
|
||||
uiEntries.entrySet().stream().forEach((entry) -> {
|
||||
UIManager.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -239,5 +239,4 @@ public class MediaViewImagePanel extends JPanel implements DataContentViewerMedi
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,520 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
|
||||
<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
|
||||
<AuxValues>
|
||||
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
|
||||
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
|
||||
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
|
||||
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
|
||||
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
|
||||
</AuxValues>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="pnOverallPanel" min="-2" pref="555" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="pnOverallPanel" alignment="0" min="-2" pref="559" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="pnOverallPanel">
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" max="-2" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="cbEnableMultiUser" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbOops" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="pnSolrSettings" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="pnDatabaseSettings" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="pnMessagingSettings" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="2" attributes="0">
|
||||
<Component id="tbOops" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="cbEnableMultiUser" alignment="2" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pnDatabaseSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pnSolrSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="pnMessagingSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="39" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Container class="javax.swing.JPanel" name="pnDatabaseSettings">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="tbDbHostname" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="lbDatabaseSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="bnTestDatabase" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="lbTestDatabase" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tbDbPort" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="tbDbUsername" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="tbDbPassword" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbTestDbWarning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="1" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="bnTestDatabase" alignment="0" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbTestDatabase" alignment="0" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
<Component id="lbDatabaseSettings" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="tbDbHostname" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbDbPort" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbDbUsername" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbDbPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbTestDbWarning" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JTextField" name="tbDbHostname">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbHostname.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbHostname.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbDbPort">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbPort.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbPort.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbDbUsername">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbUsername.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbUsername.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="tbDbPassword">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbPassword.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbDbPassword.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbDatabaseSettings">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbDatabaseSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="verticalAlignment" type="int" value="1"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnTestDatabase">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.bnTestDatabase.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnTestDatabaseActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbTestDatabase">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbTestDatabase.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="autoscrolls" type="boolean" value="true"/>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbTestDbWarning">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbTestDbWarning.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="pnSolrSettings">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="tbSolrHostname" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="lbSolrSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="bnTestSolr" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="lbTestSolr" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tbSolrPort" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbTestSolrWarning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="bnTestSolr" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbSolrSettings" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lbTestSolr" alignment="1" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbSolrHostname" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
<Component id="tbSolrPort" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbTestSolrWarning" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="lbSolrSettings">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbSolrSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbSolrHostname">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbSolrHostname.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbSolrPort">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbSolrPort.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnTestSolr">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.bnTestSolr.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnTestSolrActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbTestSolr">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbTestSolr.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbTestSolrWarning">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbTestSolrWarning.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Container class="javax.swing.JPanel" name="pnMessagingSettings">
|
||||
<Properties>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="org.netbeans.modules.form.compat2.border.EtchedBorderInfo">
|
||||
<EtchetBorder/>
|
||||
</Border>
|
||||
</Property>
|
||||
</Properties>
|
||||
|
||||
<Layout>
|
||||
<DimensionLayout dim="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="tbMsgHostname" max="32767" attributes="0"/>
|
||||
<Group type="102" attributes="0">
|
||||
<Component id="lbMessageServiceSettings" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace pref="229" max="32767" attributes="0"/>
|
||||
<Component id="bnTestMessageService" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace type="separate" max="-2" attributes="0"/>
|
||||
<Component id="lbTestMessageService" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="tbMsgPort" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="tbMsgUsername" alignment="0" max="32767" attributes="0"/>
|
||||
<Component id="tbMsgPassword" alignment="0" max="32767" attributes="0"/>
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<Component id="lbTestMessageWarning" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace min="0" pref="0" max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
<DimensionLayout dim="1">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Group type="102" alignment="0" attributes="0">
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Group type="103" groupAlignment="1" attributes="0">
|
||||
<Group type="103" groupAlignment="0" attributes="0">
|
||||
<Component id="bnTestMessageService" alignment="1" min="-2" max="-2" attributes="0"/>
|
||||
<Component id="lbMessageServiceSettings" min="-2" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<Component id="lbTestMessageService" min="-2" pref="23" max="-2" attributes="0"/>
|
||||
</Group>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbMsgHostname" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbMsgPort" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbMsgUsername" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="tbMsgPassword" min="-2" max="-2" attributes="0"/>
|
||||
<EmptySpace max="-2" attributes="0"/>
|
||||
<Component id="lbTestMessageWarning" min="-2" pref="16" max="-2" attributes="0"/>
|
||||
<EmptySpace max="32767" attributes="0"/>
|
||||
</Group>
|
||||
</Group>
|
||||
</DimensionLayout>
|
||||
</Layout>
|
||||
<SubComponents>
|
||||
<Component class="javax.swing.JLabel" name="lbMessageServiceSettings">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbMessageServiceSettings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbMsgHostname">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgHostname.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgHostname.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbMsgUsername">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgUsername.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgUsername.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbMsgPort">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgPort.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgPort.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JPasswordField" name="tbMsgPassword">
|
||||
<Properties>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="0"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgPassword.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbMsgPassword.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JButton" name="bnTestMessageService">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.bnTestMessageService.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="bnTestMessageServiceActionPerformed"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbTestMessageService">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbTestMessageService.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
<Component class="javax.swing.JLabel" name="lbTestMessageWarning">
|
||||
<Properties>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.lbTestMessageWarning.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
<Component class="javax.swing.JCheckBox" name="cbEnableMultiUser">
|
||||
<Properties>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.cbEnableMultiUser.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
<Events>
|
||||
<EventHandler event="itemStateChanged" listener="java.awt.event.ItemListener" parameters="java.awt.event.ItemEvent" handler="cbEnableMultiUserItemStateChanged"/>
|
||||
</Events>
|
||||
</Component>
|
||||
<Component class="javax.swing.JTextField" name="tbOops">
|
||||
<Properties>
|
||||
<Property name="editable" type="boolean" value="false"/>
|
||||
<Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor">
|
||||
<Font name="Tahoma" size="12" style="1"/>
|
||||
</Property>
|
||||
<Property name="foreground" type="java.awt.Color" editor="org.netbeans.beaninfo.editors.ColorEditor">
|
||||
<Color blue="0" green="0" red="ff" type="rgb"/>
|
||||
</Property>
|
||||
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
|
||||
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="MultiUserSettingsPanel.tbOops.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
|
||||
</Property>
|
||||
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
|
||||
<Border info="null"/>
|
||||
</Property>
|
||||
</Properties>
|
||||
</Component>
|
||||
</SubComponents>
|
||||
</Container>
|
||||
</SubComponents>
|
||||
</Form>
|
@ -0,0 +1,862 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import javax.swing.JTextField;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.datamodel.CaseDbConnectionInfo;
|
||||
import org.sleuthkit.datamodel.TskData.DbType;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
import org.sleuthkit.autopsy.events.MessageServiceConnectionInfo;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import java.awt.Cursor;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.ImageIcon;
|
||||
import org.openide.util.ImageUtilities;
|
||||
import org.openide.util.Lookup;
|
||||
import org.sleuthkit.autopsy.core.UserPreferencesException;
|
||||
import org.sleuthkit.autopsy.events.MessageServiceException;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
|
||||
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchServiceException;
|
||||
import org.sleuthkit.datamodel.SleuthkitCase;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
public final class MultiUserSettingsPanel extends javax.swing.JPanel {
|
||||
|
||||
private static final String HOST_NAME_OR_IP_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbHostname.toolTipText");
|
||||
private static final String PORT_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbPort.toolTipText");
|
||||
private static final String USER_NAME_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbUsername.toolTipText");
|
||||
private static final String PASSWORD_PROMPT = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbPassword.toolTipText");
|
||||
private static final String INCOMPLETE_SETTINGS_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.incomplete");
|
||||
private static final String INVALID_DB_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidDatabasePort");
|
||||
private static final String INVALID_MESSAGE_SERVICE_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidMessageServicePort");
|
||||
private static final String INVALID_INDEXING_SERVER_PORT_MSG = NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.validationErrMsg.invalidIndexingServerPort");
|
||||
private static final int DEFAULT_MESSAGE_SERVICE_PORT = 61616;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final MultiUserSettingsPanelController controller;
|
||||
private final Collection<JTextField> textBoxes = new ArrayList<>();
|
||||
private final TextBoxChangedListener textBoxChangedListener;
|
||||
private static final Logger logger = Logger.getLogger(MultiUserSettingsPanel.class.getName());
|
||||
private final ImageIcon goodIcon;
|
||||
private final ImageIcon badIcon;
|
||||
|
||||
/**
|
||||
* Creates new form AutopsyMultiUserSettingsPanel
|
||||
*
|
||||
* @param theController Controller to notify of changes.
|
||||
*/
|
||||
public MultiUserSettingsPanel(MultiUserSettingsPanelController theController) {
|
||||
initComponents();
|
||||
controller = theController;
|
||||
setSize(555, 600);
|
||||
|
||||
/**
|
||||
* Add text prompts to all of the text fields.
|
||||
*/
|
||||
Collection<TextPrompt> textPrompts = new ArrayList<>();
|
||||
textPrompts.add(new TextPrompt(HOST_NAME_OR_IP_PROMPT, tbDbHostname));
|
||||
textPrompts.add(new TextPrompt(PORT_PROMPT, tbDbPort));
|
||||
textPrompts.add(new TextPrompt(USER_NAME_PROMPT, tbDbUsername));
|
||||
textPrompts.add(new TextPrompt(PASSWORD_PROMPT, tbDbPassword));
|
||||
textPrompts.add(new TextPrompt(HOST_NAME_OR_IP_PROMPT, tbMsgHostname));
|
||||
textPrompts.add(new TextPrompt(PORT_PROMPT, tbMsgPort));
|
||||
textPrompts.add(new TextPrompt(USER_NAME_PROMPT, tbMsgUsername));
|
||||
textPrompts.add(new TextPrompt(PASSWORD_PROMPT, tbMsgPassword));
|
||||
textPrompts.add(new TextPrompt(HOST_NAME_OR_IP_PROMPT, tbSolrHostname));
|
||||
textPrompts.add(new TextPrompt(PORT_PROMPT, tbSolrPort));
|
||||
configureTextPrompts(textPrompts);
|
||||
|
||||
/* Set each textbox with a "statusIcon" property enabling the
|
||||
DocumentListeners to know which icon to erase when changes are made */
|
||||
tbDbHostname.getDocument().putProperty("statusIcon", lbTestDatabase);
|
||||
tbDbPort.getDocument().putProperty("statusIcon", lbTestDatabase);
|
||||
tbDbUsername.getDocument().putProperty("statusIcon", lbTestDatabase);
|
||||
tbDbPassword.getDocument().putProperty("statusIcon", lbTestDatabase);
|
||||
|
||||
tbSolrHostname.getDocument().putProperty("statusIcon", lbTestSolr);
|
||||
tbSolrPort.getDocument().putProperty("statusIcon", lbTestSolr);
|
||||
|
||||
tbMsgHostname.getDocument().putProperty("statusIcon", lbTestMessageService);
|
||||
tbMsgPort.getDocument().putProperty("statusIcon", lbTestMessageService);
|
||||
tbMsgUsername.getDocument().putProperty("statusIcon", lbTestMessageService);
|
||||
tbMsgPassword.getDocument().putProperty("statusIcon", lbTestMessageService);
|
||||
|
||||
/// Register for notifications when the text boxes get updated.
|
||||
textBoxChangedListener = new TextBoxChangedListener();
|
||||
textBoxes.add(tbDbHostname);
|
||||
textBoxes.add(tbDbPort);
|
||||
textBoxes.add(tbDbUsername);
|
||||
textBoxes.add(tbDbPassword);
|
||||
textBoxes.add(tbMsgHostname);
|
||||
textBoxes.add(tbMsgPort);
|
||||
textBoxes.add(tbMsgUsername);
|
||||
textBoxes.add(tbMsgPassword);
|
||||
textBoxes.add(tbSolrHostname);
|
||||
textBoxes.add(tbSolrPort);
|
||||
|
||||
addDocumentListeners(textBoxes, textBoxChangedListener);
|
||||
goodIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/good.png", false));
|
||||
badIcon = new ImageIcon(ImageUtilities.loadImage("org/sleuthkit/autopsy/images/bad.png", false));
|
||||
enableMultiUserComponents(textBoxes, cbEnableMultiUser.isSelected());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the foreground color and transparency of a collection of text
|
||||
* prompts.
|
||||
*
|
||||
* @param textPrompts The text prompts to configure.
|
||||
*/
|
||||
private static void configureTextPrompts(Collection<TextPrompt> textPrompts) {
|
||||
float alpha = 0.9f; // Mostly opaque
|
||||
for (TextPrompt textPrompt : textPrompts) {
|
||||
textPrompt.setForeground(Color.LIGHT_GRAY);
|
||||
textPrompt.changeAlpha(alpha);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a change listener to a collection of text fields.
|
||||
*
|
||||
* @param textFields The text fields.
|
||||
* @param listener The change listener.
|
||||
*/
|
||||
private static void addDocumentListeners(Collection<JTextField> textFields, TextBoxChangedListener listener) {
|
||||
for (JTextField textField : textFields) {
|
||||
textField.getDocument().addDocumentListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called from within the constructor to initialize the form.
|
||||
* WARNING: Do NOT modify this code. The content of this method is always
|
||||
* regenerated by the Form Editor.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
|
||||
private void initComponents() {
|
||||
|
||||
pnOverallPanel = new javax.swing.JPanel();
|
||||
pnDatabaseSettings = new javax.swing.JPanel();
|
||||
tbDbHostname = new javax.swing.JTextField();
|
||||
tbDbPort = new javax.swing.JTextField();
|
||||
tbDbUsername = new javax.swing.JTextField();
|
||||
tbDbPassword = new javax.swing.JPasswordField();
|
||||
lbDatabaseSettings = new javax.swing.JLabel();
|
||||
bnTestDatabase = new javax.swing.JButton();
|
||||
lbTestDatabase = new javax.swing.JLabel();
|
||||
lbTestDbWarning = new javax.swing.JLabel();
|
||||
pnSolrSettings = new javax.swing.JPanel();
|
||||
lbSolrSettings = new javax.swing.JLabel();
|
||||
tbSolrHostname = new javax.swing.JTextField();
|
||||
tbSolrPort = new javax.swing.JTextField();
|
||||
bnTestSolr = new javax.swing.JButton();
|
||||
lbTestSolr = new javax.swing.JLabel();
|
||||
lbTestSolrWarning = new javax.swing.JLabel();
|
||||
pnMessagingSettings = new javax.swing.JPanel();
|
||||
lbMessageServiceSettings = new javax.swing.JLabel();
|
||||
tbMsgHostname = new javax.swing.JTextField();
|
||||
tbMsgUsername = new javax.swing.JTextField();
|
||||
tbMsgPort = new javax.swing.JTextField();
|
||||
tbMsgPassword = new javax.swing.JPasswordField();
|
||||
bnTestMessageService = new javax.swing.JButton();
|
||||
lbTestMessageService = new javax.swing.JLabel();
|
||||
lbTestMessageWarning = new javax.swing.JLabel();
|
||||
cbEnableMultiUser = new javax.swing.JCheckBox();
|
||||
tbOops = new javax.swing.JTextField();
|
||||
|
||||
pnDatabaseSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
tbDbHostname.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbDbHostname.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbHostname.text")); // NOI18N
|
||||
tbDbHostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbHostname.toolTipText")); // NOI18N
|
||||
|
||||
tbDbPort.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbDbPort.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbPort.text")); // NOI18N
|
||||
tbDbPort.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbPort.toolTipText")); // NOI18N
|
||||
|
||||
tbDbUsername.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbDbUsername.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbUsername.text")); // NOI18N
|
||||
tbDbUsername.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbUsername.toolTipText")); // NOI18N
|
||||
|
||||
tbDbPassword.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbDbPassword.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbPassword.text")); // NOI18N
|
||||
tbDbPassword.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbDbPassword.toolTipText")); // NOI18N
|
||||
|
||||
lbDatabaseSettings.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbDatabaseSettings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbDatabaseSettings.text")); // NOI18N
|
||||
lbDatabaseSettings.setVerticalAlignment(javax.swing.SwingConstants.TOP);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnTestDatabase, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.bnTestDatabase.text")); // NOI18N
|
||||
bnTestDatabase.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnTestDatabaseActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbTestDatabase, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestDatabase.text")); // NOI18N
|
||||
lbTestDatabase.setAutoscrolls(true);
|
||||
|
||||
lbTestDbWarning.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbTestDbWarning, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestDbWarning.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout pnDatabaseSettingsLayout = new javax.swing.GroupLayout(pnDatabaseSettings);
|
||||
pnDatabaseSettings.setLayout(pnDatabaseSettingsLayout);
|
||||
pnDatabaseSettingsLayout.setHorizontalGroup(
|
||||
pnDatabaseSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnDatabaseSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnDatabaseSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tbDbHostname)
|
||||
.addGroup(pnDatabaseSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbDatabaseSettings)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(bnTestDatabase)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(tbDbPort)
|
||||
.addComponent(tbDbUsername)
|
||||
.addComponent(tbDbPassword)
|
||||
.addGroup(pnDatabaseSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbTestDbWarning)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
pnDatabaseSettingsLayout.setVerticalGroup(
|
||||
pnDatabaseSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnDatabaseSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnDatabaseSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(bnTestDatabase)
|
||||
.addComponent(lbTestDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(lbDatabaseSettings))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(tbDbHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbDbPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbDbUsername, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbDbPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbTestDbWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pnSolrSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
lbSolrSettings.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbSolrSettings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbSolrSettings.text")); // NOI18N
|
||||
|
||||
tbSolrHostname.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbSolrHostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolrHostname.toolTipText")); // NOI18N
|
||||
|
||||
tbSolrPort.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbSolrPort.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbSolrPort.toolTipText")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnTestSolr, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.bnTestSolr.text")); // NOI18N
|
||||
bnTestSolr.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnTestSolrActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbTestSolr, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestSolr.text")); // NOI18N
|
||||
|
||||
lbTestSolrWarning.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbTestSolrWarning, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestSolrWarning.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout pnSolrSettingsLayout = new javax.swing.GroupLayout(pnSolrSettings);
|
||||
pnSolrSettings.setLayout(pnSolrSettingsLayout);
|
||||
pnSolrSettingsLayout.setHorizontalGroup(
|
||||
pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnSolrSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tbSolrHostname)
|
||||
.addGroup(pnSolrSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbSolrSettings)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(bnTestSolr)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(lbTestSolr, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(tbSolrPort)
|
||||
.addGroup(pnSolrSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbTestSolrWarning)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
pnSolrSettingsLayout.setVerticalGroup(
|
||||
pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnSolrSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnSolrSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(bnTestSolr, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lbSolrSettings))
|
||||
.addComponent(lbTestSolr, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbSolrHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(tbSolrPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbTestSolrWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap())
|
||||
);
|
||||
|
||||
pnMessagingSettings.setBorder(javax.swing.BorderFactory.createEtchedBorder());
|
||||
|
||||
lbMessageServiceSettings.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbMessageServiceSettings, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbMessageServiceSettings.text")); // NOI18N
|
||||
|
||||
tbMsgHostname.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbMsgHostname.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgHostname.text")); // NOI18N
|
||||
tbMsgHostname.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgHostname.toolTipText")); // NOI18N
|
||||
|
||||
tbMsgUsername.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbMsgUsername.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgUsername.text")); // NOI18N
|
||||
tbMsgUsername.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgUsername.toolTipText")); // NOI18N
|
||||
|
||||
tbMsgPort.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbMsgPort.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgPort.text")); // NOI18N
|
||||
tbMsgPort.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgPort.toolTipText")); // NOI18N
|
||||
|
||||
tbMsgPassword.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
|
||||
tbMsgPassword.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgPassword.text")); // NOI18N
|
||||
tbMsgPassword.setToolTipText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbMsgPassword.toolTipText")); // NOI18N
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(bnTestMessageService, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.bnTestMessageService.text")); // NOI18N
|
||||
bnTestMessageService.addActionListener(new java.awt.event.ActionListener() {
|
||||
public void actionPerformed(java.awt.event.ActionEvent evt) {
|
||||
bnTestMessageServiceActionPerformed(evt);
|
||||
}
|
||||
});
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbTestMessageService, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestMessageService.text")); // NOI18N
|
||||
|
||||
lbTestMessageWarning.setForeground(new java.awt.Color(255, 0, 0));
|
||||
org.openide.awt.Mnemonics.setLocalizedText(lbTestMessageWarning, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.lbTestMessageWarning.text")); // NOI18N
|
||||
|
||||
javax.swing.GroupLayout pnMessagingSettingsLayout = new javax.swing.GroupLayout(pnMessagingSettings);
|
||||
pnMessagingSettings.setLayout(pnMessagingSettingsLayout);
|
||||
pnMessagingSettingsLayout.setHorizontalGroup(
|
||||
pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnMessagingSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(tbMsgHostname)
|
||||
.addGroup(pnMessagingSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbMessageServiceSettings)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 229, Short.MAX_VALUE)
|
||||
.addComponent(bnTestMessageService)
|
||||
.addGap(18, 18, 18)
|
||||
.addComponent(lbTestMessageService, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addComponent(tbMsgPort)
|
||||
.addComponent(tbMsgUsername)
|
||||
.addComponent(tbMsgPassword)
|
||||
.addGroup(pnMessagingSettingsLayout.createSequentialGroup()
|
||||
.addComponent(lbTestMessageWarning)
|
||||
.addGap(0, 0, Short.MAX_VALUE)))
|
||||
.addContainerGap())
|
||||
);
|
||||
pnMessagingSettingsLayout.setVerticalGroup(
|
||||
pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(pnMessagingSettingsLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addGroup(pnMessagingSettingsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(bnTestMessageService, javax.swing.GroupLayout.Alignment.TRAILING)
|
||||
.addComponent(lbMessageServiceSettings))
|
||||
.addComponent(lbTestMessageService, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbMsgHostname, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbMsgPort, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbMsgUsername, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbMsgPassword, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(lbTestMessageWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 16, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
org.openide.awt.Mnemonics.setLocalizedText(cbEnableMultiUser, org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.cbEnableMultiUser.text")); // NOI18N
|
||||
cbEnableMultiUser.addItemListener(new java.awt.event.ItemListener() {
|
||||
public void itemStateChanged(java.awt.event.ItemEvent evt) {
|
||||
cbEnableMultiUserItemStateChanged(evt);
|
||||
}
|
||||
});
|
||||
|
||||
tbOops.setEditable(false);
|
||||
tbOops.setFont(new java.awt.Font("Tahoma", 1, 12)); // NOI18N
|
||||
tbOops.setForeground(new java.awt.Color(255, 0, 0));
|
||||
tbOops.setText(org.openide.util.NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.tbOops.text")); // NOI18N
|
||||
tbOops.setBorder(null);
|
||||
|
||||
javax.swing.GroupLayout pnOverallPanelLayout = new javax.swing.GroupLayout(pnOverallPanel);
|
||||
pnOverallPanel.setLayout(pnOverallPanelLayout);
|
||||
pnOverallPanelLayout.setHorizontalGroup(
|
||||
pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnOverallPanelLayout.createSequentialGroup()
|
||||
.addContainerGap()
|
||||
.addGroup(pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
|
||||
.addGroup(pnOverallPanelLayout.createSequentialGroup()
|
||||
.addComponent(cbEnableMultiUser)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(tbOops))
|
||||
.addComponent(pnSolrSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(pnDatabaseSettings, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
|
||||
.addComponent(pnMessagingSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
|
||||
.addContainerGap())
|
||||
);
|
||||
pnOverallPanelLayout.setVerticalGroup(
|
||||
pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnOverallPanelLayout.createSequentialGroup()
|
||||
.addGroup(pnOverallPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
|
||||
.addComponent(tbOops, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addComponent(cbEnableMultiUser))
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnDatabaseSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnSolrSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
|
||||
.addComponent(pnMessagingSettings, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
.addContainerGap(39, Short.MAX_VALUE))
|
||||
);
|
||||
|
||||
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
|
||||
this.setLayout(layout);
|
||||
layout.setHorizontalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(pnOverallPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 555, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
);
|
||||
layout.setVerticalGroup(
|
||||
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
|
||||
.addComponent(pnOverallPanel, javax.swing.GroupLayout.PREFERRED_SIZE, 559, javax.swing.GroupLayout.PREFERRED_SIZE)
|
||||
);
|
||||
}// </editor-fold>//GEN-END:initComponents
|
||||
|
||||
/**
|
||||
* Enables/disables the multi-user settings, based upon input provided
|
||||
*
|
||||
* @param enabled true means enable, false means disable
|
||||
*/
|
||||
private static void enableMultiUserComponents(Collection<JTextField> textFields, boolean enabled) {
|
||||
for (JTextField textField : textFields) {
|
||||
textField.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
private void cbEnableMultiUserItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_cbEnableMultiUserItemStateChanged
|
||||
if (!cbEnableMultiUser.isSelected()) {
|
||||
tbOops.setText("");
|
||||
bnTestDatabase.setEnabled(false);
|
||||
lbTestDatabase.setIcon(null);
|
||||
bnTestSolr.setEnabled(false);
|
||||
lbTestSolr.setIcon(null);
|
||||
bnTestMessageService.setEnabled(false);
|
||||
lbTestMessageService.setIcon(null);
|
||||
lbTestDbWarning.setText("");
|
||||
lbTestSolrWarning.setText("");
|
||||
lbTestMessageWarning.setText("");
|
||||
}
|
||||
enableMultiUserComponents(textBoxes, cbEnableMultiUser.isSelected());
|
||||
controller.changed();
|
||||
}//GEN-LAST:event_cbEnableMultiUserItemStateChanged
|
||||
|
||||
private void bnTestDatabaseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestDatabaseActionPerformed
|
||||
lbTestDatabase.setIcon(null);
|
||||
lbTestDbWarning.setText("");
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
try {
|
||||
CaseDbConnectionInfo info = new CaseDbConnectionInfo(
|
||||
this.tbDbHostname.getText().trim(),
|
||||
this.tbDbPort.getText().trim(),
|
||||
this.tbDbUsername.getText().trim(),
|
||||
new String(this.tbDbPassword.getPassword()),
|
||||
DbType.POSTGRESQL);
|
||||
|
||||
SleuthkitCase.tryConnect(info);
|
||||
lbTestDatabase.setIcon(goodIcon);
|
||||
lbTestDbWarning.setText("");
|
||||
} catch (TskCoreException ex) {
|
||||
lbTestDatabase.setIcon(badIcon);
|
||||
lbTestDbWarning.setText(ex.getMessage());
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}//GEN-LAST:event_bnTestDatabaseActionPerformed
|
||||
|
||||
private void bnTestMessageServiceActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestMessageServiceActionPerformed
|
||||
lbTestMessageService.setIcon(null);
|
||||
lbTestMessageWarning.setText("");
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
|
||||
int port;
|
||||
try {
|
||||
port = Integer.parseInt(this.tbMsgPort.getText().trim());
|
||||
} catch (NumberFormatException ex) {
|
||||
lbTestMessageService.setIcon(badIcon);
|
||||
lbTestMessageWarning.setText(NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.InvalidPortNumber"));
|
||||
return;
|
||||
}
|
||||
|
||||
MessageServiceConnectionInfo info = new MessageServiceConnectionInfo(
|
||||
this.tbMsgHostname.getText().trim(),
|
||||
port,
|
||||
this.tbMsgUsername.getText().trim(),
|
||||
new String(this.tbMsgPassword.getPassword()));
|
||||
try {
|
||||
info.tryConnect();
|
||||
lbTestMessageService.setIcon(goodIcon);
|
||||
lbTestMessageWarning.setText("");
|
||||
} catch (MessageServiceException ex) {
|
||||
lbTestMessageService.setIcon(badIcon);
|
||||
lbTestMessageWarning.setText(ex.getMessage());
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}//GEN-LAST:event_bnTestMessageServiceActionPerformed
|
||||
|
||||
private void bnTestSolrActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnTestSolrActionPerformed
|
||||
lbTestSolr.setIcon(null);
|
||||
lbTestSolrWarning.setText("");
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
|
||||
|
||||
KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class);
|
||||
try {
|
||||
if (kwsService != null) {
|
||||
int port = Integer.parseInt(tbSolrPort.getText().trim());
|
||||
kwsService.tryConnect(tbSolrHostname.getText().trim(), port);
|
||||
lbTestSolr.setIcon(goodIcon);
|
||||
lbTestSolrWarning.setText("");
|
||||
} else {
|
||||
lbTestSolr.setIcon(badIcon);
|
||||
lbTestSolrWarning.setText(NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.KeywordSearchNull"));
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
lbTestSolr.setIcon(badIcon);
|
||||
lbTestSolrWarning.setText(NbBundle.getMessage(MultiUserSettingsPanel.class, "MultiUserSettingsPanel.InvalidPortNumber"));
|
||||
} catch (KeywordSearchServiceException ex) {
|
||||
lbTestSolr.setIcon(badIcon);
|
||||
lbTestSolrWarning.setText(ex.getMessage());
|
||||
} finally {
|
||||
setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
|
||||
}
|
||||
}//GEN-LAST:event_bnTestSolrActionPerformed
|
||||
|
||||
void load() {
|
||||
lbTestDatabase.setIcon(null);
|
||||
lbTestSolr.setIcon(null);
|
||||
lbTestMessageService.setIcon(null);
|
||||
lbTestDbWarning.setText("");
|
||||
lbTestSolrWarning.setText("");
|
||||
lbTestMessageWarning.setText("");
|
||||
|
||||
try {
|
||||
CaseDbConnectionInfo dbInfo = UserPreferences.getDatabaseConnectionInfo();
|
||||
tbDbHostname.setText(dbInfo.getHost().trim());
|
||||
tbDbPort.setText(dbInfo.getPort().trim());
|
||||
tbDbUsername.setText(dbInfo.getUserName().trim());
|
||||
tbDbPassword.setText(dbInfo.getPassword());
|
||||
} catch (UserPreferencesException ex) {
|
||||
logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
MessageServiceConnectionInfo msgServiceInfo = UserPreferences.getMessageServiceConnectionInfo();
|
||||
tbMsgHostname.setText(msgServiceInfo.getHost().trim());
|
||||
tbMsgPort.setText(Integer.toString(msgServiceInfo.getPort()));
|
||||
tbMsgUsername.setText(msgServiceInfo.getUserName().trim());
|
||||
tbMsgPassword.setText(msgServiceInfo.getPassword());
|
||||
} catch (UserPreferencesException ex) {
|
||||
logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS
|
||||
}
|
||||
|
||||
String indexingServerHost = UserPreferences.getIndexingServerHost().trim();
|
||||
if (!indexingServerHost.isEmpty()) {
|
||||
tbSolrHostname.setText(indexingServerHost);
|
||||
}
|
||||
String indexingServerPort = UserPreferences.getIndexingServerPort().trim();
|
||||
if (portNumberIsValid(indexingServerPort)) {
|
||||
tbSolrPort.setText(indexingServerPort);
|
||||
}
|
||||
|
||||
lbTestDatabase.setIcon(null);
|
||||
lbTestSolr.setIcon(null);
|
||||
lbTestMessageService.setIcon(null);
|
||||
|
||||
bnTestDatabase.setEnabled(false);
|
||||
bnTestSolr.setEnabled(false);
|
||||
bnTestMessageService.setEnabled(false);
|
||||
|
||||
cbEnableMultiUser.setSelected(UserPreferences.getIsMultiUserModeEnabled());
|
||||
this.valid(); // trigger validation to enable buttons based on current settings
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not values have been entered in all of the database
|
||||
* settings text fields.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
private boolean databaseFieldsArePopulated() {
|
||||
return !tbDbHostname.getText().trim().isEmpty()
|
||||
&& !tbDbPort.getText().trim().isEmpty()
|
||||
&& !tbDbUsername.getText().trim().isEmpty()
|
||||
&& tbDbPassword.getPassword().length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not values have been entered in all of the Solr settings
|
||||
* text fields.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
private boolean solrFieldsArePopulated() {
|
||||
return !tbSolrHostname.getText().trim().isEmpty()
|
||||
&& !tbSolrPort.getText().trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not values have been entered in all of the message
|
||||
* service settings text fields.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
private boolean messageServiceFieldsArePopulated() {
|
||||
return !tbMsgHostname.getText().trim().isEmpty()
|
||||
&& !tbMsgPort.getText().trim().isEmpty()
|
||||
&& !tbMsgUsername.getText().trim().isEmpty()
|
||||
&& tbMsgPassword.getPassword().length != 0;
|
||||
}
|
||||
|
||||
void store() {
|
||||
DbType dbType = DbType.SQLITE;
|
||||
|
||||
if (cbEnableMultiUser.isSelected()) {
|
||||
dbType = DbType.POSTGRESQL;
|
||||
}
|
||||
|
||||
UserPreferences.setIsMultiUserModeEnabled(cbEnableMultiUser.isSelected());
|
||||
|
||||
CaseDbConnectionInfo info = new CaseDbConnectionInfo(
|
||||
tbDbHostname.getText().trim(),
|
||||
tbDbPort.getText().trim(),
|
||||
tbDbUsername.getText().trim(),
|
||||
new String(tbDbPassword.getPassword()),
|
||||
dbType);
|
||||
|
||||
try {
|
||||
UserPreferences.setDatabaseConnectionInfo(info);
|
||||
} catch (UserPreferencesException ex) {
|
||||
logger.log(Level.SEVERE, "Error accessing case database connection info", ex); //NON-NLS
|
||||
}
|
||||
|
||||
int port = 0;
|
||||
try {
|
||||
port = Integer.parseInt(this.tbMsgPort.getText().trim());
|
||||
} catch (NumberFormatException ex) {
|
||||
logger.log(Level.SEVERE, "Bad port setting", ex);
|
||||
}
|
||||
|
||||
MessageServiceConnectionInfo msgServiceInfo = new MessageServiceConnectionInfo(
|
||||
tbMsgHostname.getText().trim(),
|
||||
port,
|
||||
tbMsgUsername.getText().trim(),
|
||||
new String(tbMsgPassword.getPassword()));
|
||||
|
||||
try {
|
||||
UserPreferences.setMessageServiceConnectionInfo(msgServiceInfo);
|
||||
} catch (UserPreferencesException ex) {
|
||||
logger.log(Level.SEVERE, "Error accessing messaging service connection info", ex); //NON-NLS
|
||||
}
|
||||
|
||||
UserPreferences.setIndexingServerHost(tbSolrHostname.getText().trim());
|
||||
UserPreferences.setIndexingServerPort(Integer.parseInt(tbSolrPort.getText().trim()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the form is filled out correctly for our usage.
|
||||
*
|
||||
* @return true if it's okay, false otherwise.
|
||||
*/
|
||||
boolean valid() {
|
||||
tbOops.setText("");
|
||||
|
||||
if (cbEnableMultiUser.isSelected()) {
|
||||
return checkFieldsAndEnableButtons()
|
||||
&& databaseSettingsAreValid()
|
||||
&& indexingServerSettingsAreValid()
|
||||
&& messageServiceSettingsAreValid();
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not all of the settings components are populated and
|
||||
* sets the test buttons appropriately.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean checkFieldsAndEnableButtons() {
|
||||
boolean result = true;
|
||||
|
||||
boolean dbPopulated = databaseFieldsArePopulated();
|
||||
boolean solrPopulated = solrFieldsArePopulated();
|
||||
boolean messageServicePopulated = messageServiceFieldsArePopulated();
|
||||
|
||||
// PostgreSQL Database
|
||||
bnTestDatabase.setEnabled(dbPopulated);
|
||||
|
||||
// Solr Indexing
|
||||
bnTestSolr.setEnabled(solrPopulated);
|
||||
|
||||
// ActiveMQ Messaging
|
||||
bnTestMessageService.setEnabled(messageServicePopulated);
|
||||
|
||||
if (!dbPopulated || !solrPopulated || !messageServicePopulated) {
|
||||
// We don't even have everything filled out
|
||||
result = false;
|
||||
tbOops.setText(INCOMPLETE_SETTINGS_MSG);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not the database settings are valid.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean databaseSettingsAreValid() {
|
||||
if (portNumberIsValid(tbDbPort.getText().trim())) {
|
||||
return true;
|
||||
} else {
|
||||
tbOops.setText(INVALID_DB_PORT_MSG);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not the message service settings are valid.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean messageServiceSettingsAreValid() {
|
||||
if (!portNumberIsValid(tbMsgPort.getText().trim())) {
|
||||
tbOops.setText(INVALID_MESSAGE_SERVICE_PORT_MSG);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests whether or not the indexing server settings are valid.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
boolean indexingServerSettingsAreValid() {
|
||||
if (!portNumberIsValid(tbSolrPort.getText().trim())) {
|
||||
tbOops.setText(INVALID_INDEXING_SERVER_PORT_MSG);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether or not a port number is within the range of valid port
|
||||
* numbers.
|
||||
*
|
||||
* @param portNumber The port number as a string.
|
||||
*
|
||||
* @return True or false.
|
||||
*/
|
||||
private static boolean portNumberIsValid(String portNumber) {
|
||||
try {
|
||||
int value = Integer.parseInt(portNumber);
|
||||
if (value < 0 || value > 65535) { // invalid port numbers
|
||||
return false;
|
||||
}
|
||||
} catch (NumberFormatException detailsNotImportant) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Variables declaration - do not modify//GEN-BEGIN:variables
|
||||
private javax.swing.JButton bnTestDatabase;
|
||||
private javax.swing.JButton bnTestMessageService;
|
||||
private javax.swing.JButton bnTestSolr;
|
||||
private javax.swing.JCheckBox cbEnableMultiUser;
|
||||
private javax.swing.JLabel lbDatabaseSettings;
|
||||
private javax.swing.JLabel lbMessageServiceSettings;
|
||||
private javax.swing.JLabel lbSolrSettings;
|
||||
private javax.swing.JLabel lbTestDatabase;
|
||||
private javax.swing.JLabel lbTestDbWarning;
|
||||
private javax.swing.JLabel lbTestMessageService;
|
||||
private javax.swing.JLabel lbTestMessageWarning;
|
||||
private javax.swing.JLabel lbTestSolr;
|
||||
private javax.swing.JLabel lbTestSolrWarning;
|
||||
private javax.swing.JPanel pnDatabaseSettings;
|
||||
private javax.swing.JPanel pnMessagingSettings;
|
||||
private javax.swing.JPanel pnOverallPanel;
|
||||
private javax.swing.JPanel pnSolrSettings;
|
||||
private javax.swing.JTextField tbDbHostname;
|
||||
private javax.swing.JPasswordField tbDbPassword;
|
||||
private javax.swing.JTextField tbDbPort;
|
||||
private javax.swing.JTextField tbDbUsername;
|
||||
private javax.swing.JTextField tbMsgHostname;
|
||||
private javax.swing.JPasswordField tbMsgPassword;
|
||||
private javax.swing.JTextField tbMsgPort;
|
||||
private javax.swing.JTextField tbMsgUsername;
|
||||
private javax.swing.JTextField tbOops;
|
||||
private javax.swing.JTextField tbSolrHostname;
|
||||
private javax.swing.JTextField tbSolrPort;
|
||||
// End of variables declaration//GEN-END:variables
|
||||
|
||||
/**
|
||||
* Used to listen for changes in text boxes. It lets the panel know things
|
||||
* have been updated and that validation needs to happen.
|
||||
*/
|
||||
class TextBoxChangedListener implements DocumentListener {
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
Object statusIcon = e.getDocument().getProperty("statusIcon");
|
||||
if (statusIcon != null) {
|
||||
((javax.swing.JLabel) statusIcon).setIcon(null);
|
||||
}
|
||||
controller.changed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
Object statusIcon = e.getDocument().getProperty("statusIcon");
|
||||
if (statusIcon != null) {
|
||||
((javax.swing.JLabel) statusIcon).setIcon(null);
|
||||
}
|
||||
controller.changed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
Object statusIcon = e.getDocument().getProperty("statusIcon");
|
||||
if (statusIcon != null) {
|
||||
((javax.swing.JLabel) statusIcon).setIcon(null);
|
||||
}
|
||||
controller.changed();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.beans.PropertyChangeListener;
|
||||
import java.beans.PropertyChangeSupport;
|
||||
import javax.swing.JComponent;
|
||||
import org.netbeans.spi.options.OptionsPanelController;
|
||||
import org.openide.util.HelpCtx;
|
||||
import org.openide.util.Lookup;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
@OptionsPanelController.TopLevelRegistration(categoryName = "#OptionsCategory_Name_Multi_User_Settings",
|
||||
iconBase = "org/sleuthkit/autopsy/images/User-Group-icon-green32.png",
|
||||
position = 2,
|
||||
keywords = "#OptionsCategory_Keywords_Multi_User_Options",
|
||||
keywordsCategory = "Multi-user")
|
||||
public final class MultiUserSettingsPanelController extends OptionsPanelController {
|
||||
|
||||
private MultiUserSettingsPanel panel;
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
private boolean changed;
|
||||
private static final Logger logger = Logger.getLogger(MultiUserSettingsPanelController.class.getName());
|
||||
|
||||
@Override
|
||||
public void update() {
|
||||
getPanel().load();
|
||||
changed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyChanges() {
|
||||
getPanel().store();
|
||||
changed = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return getPanel().valid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChanged() {
|
||||
return changed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HelpCtx getHelpCtx() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JComponent getComponent(Lookup masterLookup) {
|
||||
return getPanel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addPropertyChangeListener(PropertyChangeListener l) {
|
||||
if (pcs.getPropertyChangeListeners().length == 0) {
|
||||
pcs.addPropertyChangeListener(l);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePropertyChangeListener(PropertyChangeListener l) {
|
||||
/**
|
||||
* Note the NetBeans Framework does not appear to call this at all. We
|
||||
* are using NetBeans 7.3.1 Build 201306052037. Perhaps in a future
|
||||
* version of the Framework this will be resolved, but for now, simply
|
||||
* don't unregister anything and add one time only in the
|
||||
* addPropertyChangeListener() method above.
|
||||
*/
|
||||
}
|
||||
|
||||
private MultiUserSettingsPanel getPanel() {
|
||||
if (panel == null) {
|
||||
panel = new MultiUserSettingsPanel(this);
|
||||
}
|
||||
return panel;
|
||||
}
|
||||
|
||||
void changed() {
|
||||
if (!changed) {
|
||||
changed = true;
|
||||
|
||||
try {
|
||||
pcs.firePropertyChange(OptionsPanelController.PROP_CHANGED, false, true);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "GeneralOptionsPanelController listener threw exception", e); //NON-NLS
|
||||
MessageNotifyUtil.Notify.show(
|
||||
NbBundle.getMessage(this.getClass(), "GeneralOptionsPanelController.moduleErr"),
|
||||
NbBundle.getMessage(this.getClass(), "GeneralOptionsPanelController.moduleErr.msg"),
|
||||
MessageNotifyUtil.MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
pcs.firePropertyChange(OptionsPanelController.PROP_VALID, null, null);
|
||||
} catch (Exception e) {
|
||||
logger.log(Level.SEVERE, "GeneralOptionsPanelController listener threw exception", e); //NON-NLS
|
||||
MessageNotifyUtil.Notify.show(
|
||||
NbBundle.getMessage(this.getClass(), "GeneralOptionsPanelController.moduleErr"),
|
||||
NbBundle.getMessage(this.getClass(), "GeneralOptionsPanelController.moduleErr.msg"),
|
||||
MessageNotifyUtil.MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
}
|
@ -33,7 +33,7 @@ import org.openide.awt.HtmlBrowser;
|
||||
import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Implements a hyperlink to the Offline Documentation.
|
||||
|
@ -35,7 +35,7 @@ import org.openide.util.NbBundle;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
|
||||
/**
|
||||
* Implements a hyperlink to the Online Documentation.
|
||||
|
206
Core/src/org/sleuthkit/autopsy/corecomponents/TextPrompt.java
Normal file
206
Core/src/org/sleuthkit/autopsy/corecomponents/TextPrompt.java
Normal file
@ -0,0 +1,206 @@
|
||||
package org.sleuthkit.autopsy.corecomponents;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.*;
|
||||
import javax.swing.event.*;
|
||||
import javax.swing.text.*;
|
||||
|
||||
/**
|
||||
* The TextPrompt class will display a prompt over top of a text component when
|
||||
* the Document of the text field is empty. The Show property is used to
|
||||
* determine the visibility of the prompt.
|
||||
*
|
||||
* The Font and foreground Color of the prompt will default to those properties
|
||||
* of the parent text component. You are free to change the properties after
|
||||
* class construction. From:
|
||||
* https://tips4java.wordpress.com/2009/11/29/text-prompt/
|
||||
*/
|
||||
public final class TextPrompt extends JLabel
|
||||
implements FocusListener, DocumentListener {
|
||||
|
||||
public enum Show {
|
||||
|
||||
ALWAYS,
|
||||
FOCUS_GAINED,
|
||||
FOCUS_LOST;
|
||||
}
|
||||
|
||||
private JTextComponent component;
|
||||
private Document document;
|
||||
|
||||
private Show show;
|
||||
private boolean showPromptOnce;
|
||||
private int focusLost;
|
||||
|
||||
public TextPrompt(String text, JTextComponent component) {
|
||||
this(text, component, Show.ALWAYS);
|
||||
}
|
||||
|
||||
public TextPrompt(String text, JTextComponent component, Show show) {
|
||||
this.component = component;
|
||||
setShow(show);
|
||||
document = component.getDocument();
|
||||
|
||||
setText(text);
|
||||
setFont(component.getFont());
|
||||
setForeground(component.getForeground());
|
||||
setBorder(new EmptyBorder(component.getInsets()));
|
||||
setHorizontalAlignment(JLabel.LEADING);
|
||||
|
||||
component.addFocusListener(this);
|
||||
document.addDocumentListener(this);
|
||||
|
||||
component.setLayout(new BorderLayout());
|
||||
component.add(this);
|
||||
checkForPrompt();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to change the alpha value of the current foreground
|
||||
* Color to the specifice value.
|
||||
*
|
||||
* @param alpha value in the range of 0 - 1.0.
|
||||
*/
|
||||
public void changeAlpha(float alpha) {
|
||||
changeAlpha((int) (alpha * 255));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to change the alpha value of the current foreground
|
||||
* Color to the specifice value.
|
||||
*
|
||||
* @param alpha value in the range of 0 - 255.
|
||||
*/
|
||||
public void changeAlpha(int alpha) {
|
||||
alpha = alpha > 255 ? 255 : alpha < 0 ? 0 : alpha;
|
||||
|
||||
Color foreground = getForeground();
|
||||
int red = foreground.getRed();
|
||||
int green = foreground.getGreen();
|
||||
int blue = foreground.getBlue();
|
||||
|
||||
Color withAlpha = new Color(red, green, blue, alpha);
|
||||
super.setForeground(withAlpha);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to change the style of the current Font. The style
|
||||
* values are found in the Font class. Common values might be: Font.BOLD,
|
||||
* Font.ITALIC and Font.BOLD + Font.ITALIC.
|
||||
*
|
||||
* @param style value representing the the new style of the Font.
|
||||
*/
|
||||
public void changeStyle(int style) {
|
||||
setFont(getFont().deriveFont(style));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Show property
|
||||
*
|
||||
* @return the Show property.
|
||||
*/
|
||||
public Show getShow() {
|
||||
return show;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the prompt Show property to control when the promt is shown. Valid
|
||||
* values are:
|
||||
*
|
||||
* Show.AWLAYS (default) - always show the prompt Show.Focus_GAINED - show
|
||||
* the prompt when the component gains focus (and hide the prompt when focus
|
||||
* is lost) Show.Focus_LOST - show the prompt when the component loses focus
|
||||
* (and hide the prompt when focus is gained)
|
||||
*
|
||||
* @param show a valid Show enum
|
||||
*/
|
||||
public void setShow(Show show) {
|
||||
this.show = show;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the showPromptOnce property
|
||||
*
|
||||
* @return the showPromptOnce property.
|
||||
*/
|
||||
public boolean getShowPromptOnce() {
|
||||
return showPromptOnce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the prompt once. Once the component has gained/lost focus once, the
|
||||
* prompt will not be shown again.
|
||||
*
|
||||
* @param showPromptOnce when true the prompt will only be shown once,
|
||||
* otherwise it will be shown repeatedly.
|
||||
*/
|
||||
public void setShowPromptOnce(boolean showPromptOnce) {
|
||||
this.showPromptOnce = showPromptOnce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the prompt should be visible or not. The visibility will
|
||||
* change on updates to the Document and on focus changes.
|
||||
*/
|
||||
private void checkForPrompt() {
|
||||
// Text has been entered, remove the prompt
|
||||
|
||||
if (document.getLength() > 0) {
|
||||
setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Prompt has already been shown once, remove it
|
||||
if (showPromptOnce && focusLost > 0) {
|
||||
setVisible(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the Show property and component focus to determine if the
|
||||
// prompt should be displayed.
|
||||
if (component.hasFocus()) {
|
||||
if (show == Show.ALWAYS
|
||||
|| show == Show.FOCUS_GAINED) {
|
||||
setVisible(true);
|
||||
} else {
|
||||
setVisible(false);
|
||||
}
|
||||
} else {
|
||||
if (show == Show.ALWAYS
|
||||
|| show == Show.FOCUS_LOST) {
|
||||
setVisible(true);
|
||||
} else {
|
||||
setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement FocusListener
|
||||
@Override
|
||||
public void focusGained(FocusEvent e) {
|
||||
checkForPrompt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent e) {
|
||||
focusLost++;
|
||||
checkForPrompt();
|
||||
}
|
||||
|
||||
// Implement DocumentListener
|
||||
@Override
|
||||
public void insertUpdate(DocumentEvent e) {
|
||||
checkForPrompt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeUpdate(DocumentEvent e) {
|
||||
checkForPrompt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changedUpdate(DocumentEvent e) {
|
||||
}
|
||||
}
|
BIN
Core/src/org/sleuthkit/autopsy/corecomponents/checkbox32.png
Normal file
BIN
Core/src/org/sleuthkit/autopsy/corecomponents/checkbox32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
@ -18,14 +18,12 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.coreutils;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.util.logging.Filter;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogRecord;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.openide.util.lookup.ServiceProvider;
|
||||
import org.netbeans.core.NbErrorManager;
|
||||
|
||||
@ -62,32 +60,12 @@ public class AutopsyExceptionHandler extends Handler {
|
||||
public void publish(LogRecord record) {
|
||||
|
||||
if (isLoggable(record)) {
|
||||
final String title = getTitleForLevelValue(record.getLevel().intValue());
|
||||
final String message = formatExplanation(record);
|
||||
|
||||
if (record.getMessage() != null) {
|
||||
// Throwable was anticipated, caught and logged. Display log message and throwable message.
|
||||
|
||||
final int levelValue = record.getLevel().intValue();
|
||||
|
||||
final Component parentComponent = null; // Use default window frame.
|
||||
final String message = formatExplanation(record);
|
||||
final String title = getTitleForLevelValue(levelValue);
|
||||
final int messageType = getMessageTypeForLevelValue(levelValue);
|
||||
|
||||
// publish() was probably not called from the EDT, so run the message box there instead of here.
|
||||
//only show the dialog in dev builds
|
||||
if (buildType == Version.Type.DEVELOPMENT) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
JOptionPane.showMessageDialog(
|
||||
parentComponent,
|
||||
message,
|
||||
title,
|
||||
messageType);
|
||||
}
|
||||
});
|
||||
}
|
||||
MessageNotifyUtil.Notify.error(title, message);
|
||||
logger.log(Level.SEVERE, "Unexpected error: " + title + ", " + message); //NON-NLS
|
||||
} else {
|
||||
// Throwable (unanticipated) error. Use built-in exception handler to offer details, stacktrace.
|
||||
|
@ -28,6 +28,7 @@ import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import org.sleuthkit.autopsy.core.UserPreferences;
|
||||
|
||||
/**
|
||||
* Executes a command line using an operating system process with a configurable
|
||||
@ -41,7 +42,10 @@ public final class ExecUtil {
|
||||
/**
|
||||
* The execute() methods do a wait() with a timeout on the executing process
|
||||
* and query a process terminator each time the timeout expires to determine
|
||||
* whether or not to kill the process.
|
||||
* whether or not to kill the process. See
|
||||
* DataSourceIngestModuleProcessTerminator and
|
||||
* FileIngestModuleProcessTerminator as examples of ProcessTerminator
|
||||
* implementations.
|
||||
*/
|
||||
public interface ProcessTerminator {
|
||||
|
||||
@ -74,6 +78,24 @@ public final class ExecUtil {
|
||||
this.startTimeInSeconds = (new Date().getTime()) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a process terminator that can be used to kill a process after
|
||||
* it has run for a given period of time. Maximum allowable run time is
|
||||
* set via Autopsy Options panel. If the process termination
|
||||
* functionality is disabled then the maximum allowable time is set to
|
||||
* MAX_INT seconds.
|
||||
*/
|
||||
public TimedProcessTerminator() {
|
||||
if (UserPreferences.getIsTimeOutEnabled() && UserPreferences.getProcessTimeOutHrs() > 0) {
|
||||
// user specified time out
|
||||
this.maxRunTimeInSeconds = UserPreferences.getProcessTimeOutHrs() * 3600;
|
||||
} else {
|
||||
// never time out
|
||||
this.maxRunTimeInSeconds = Long.MAX_VALUE;
|
||||
}
|
||||
this.startTimeInSeconds = (new Date().getTime()) / 1000;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
|
@ -163,8 +163,8 @@ public class FileUtil {
|
||||
* @return escaped string
|
||||
*/
|
||||
public static String escapeFileName(String fileName) {
|
||||
//for now escaping / (not valid in file name, at least on Windows)
|
||||
//with underscores. Windows/Java seem to ignore \\/ and \\\\/ escapings
|
||||
return fileName.replaceAll("/", "_");
|
||||
//for now escaping /:"*?<>| (not valid in file name, at least on Windows)
|
||||
//with underscores. We are only keeping \ as it could be part of the path.
|
||||
return fileName.replaceAll("[/:\"*?<>|]+", "_");
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.coreutils;
|
||||
|
||||
import java.util.Deque;
|
||||
import java.util.Objects;
|
||||
import javafx.beans.property.Property;
|
||||
import javafx.beans.property.ReadOnlyBooleanProperty;
|
||||
@ -143,7 +144,6 @@ public class History<T> {
|
||||
* @throws IllegalArgumentException if newState == null
|
||||
*/
|
||||
synchronized public void advance(T newState) throws IllegalArgumentException {
|
||||
|
||||
if (newState != null && Objects.equals(currentState.get(), newState) == false) {
|
||||
if (currentState.get() != null) {
|
||||
historyStack.push(currentState.get());
|
||||
|
@ -56,7 +56,6 @@ import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Utilities for working with Images and creating thumbnails. Reuses thumbnails
|
||||
* by storing them in the case's cache directory.
|
||||
*/
|
||||
@ -140,9 +139,6 @@ public class ImageUtils {
|
||||
= Executors.newSingleThreadExecutor(new BasicThreadFactory.Builder()
|
||||
.namingPattern("icon saver-%d").build());
|
||||
|
||||
private ImageUtils() {
|
||||
}
|
||||
|
||||
public static List<String> getSupportedImageExtensions() {
|
||||
return Collections.unmodifiableList(SUPPORTED_IMAGE_EXTENSIONS);
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2014 Basis Technology Corp.
|
||||
* Copyright 2012-2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -18,17 +18,20 @@
|
||||
*/
|
||||
package org.sleuthkit.autopsy.coreutils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.Handler;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
/**
|
||||
* Autopsy specialization of the Java Logger class with custom file handlers.
|
||||
* Note that the custom loggers are not obtained from the global log manager.
|
||||
*/
|
||||
public final class Logger extends java.util.logging.Logger {
|
||||
|
||||
@ -37,66 +40,81 @@ public final class Logger extends java.util.logging.Logger {
|
||||
private static final int LOG_FILE_COUNT = 10;
|
||||
private static final String LOG_WITHOUT_STACK_TRACES = "autopsy.log"; //NON-NLS
|
||||
private static final String LOG_WITH_STACK_TRACES = "autopsy_traces.log"; //NON-NLS
|
||||
private static final Handler console = new java.util.logging.ConsoleHandler();
|
||||
private static final Object fileHandlerLock = new Object();
|
||||
private static FileHandler userFriendlyLogFile = createFileHandler(PlatformUtil.getLogDirectory(), LOG_WITHOUT_STACK_TRACES);
|
||||
private static FileHandler developersLogFile = createFileHandler(PlatformUtil.getLogDirectory(), LOG_WITH_STACK_TRACES);
|
||||
private static final Map<String, Logger> namesToLoggers = new HashMap<>();
|
||||
private static final Handler consoleHandler = new java.util.logging.ConsoleHandler();
|
||||
private static FileHandler userFriendlyHandler = createFileHandlerWithoutTraces(PlatformUtil.getLogDirectory());
|
||||
private static FileHandler developerFriendlyHandler = createFileHandlerWithTraces(PlatformUtil.getLogDirectory());
|
||||
|
||||
private static FileHandler createFileHandler(String logDirectory, String fileName) {
|
||||
/**
|
||||
* Creates a custom file handler with a custom message formatter that does
|
||||
* not include stack traces.
|
||||
*
|
||||
* @param logDirectory The directory where the log files should reside.
|
||||
*
|
||||
* @return A custom file handler.
|
||||
*/
|
||||
private static FileHandler createFileHandlerWithoutTraces(String logDirectory) {
|
||||
String logFilePath = Paths.get(logDirectory, LOG_WITHOUT_STACK_TRACES).toString();
|
||||
try {
|
||||
FileHandler f = new FileHandler(logDirectory + File.separator + fileName, LOG_SIZE, LOG_FILE_COUNT);
|
||||
f.setEncoding(LOG_ENCODING);
|
||||
switch (fileName) {
|
||||
case LOG_WITHOUT_STACK_TRACES:
|
||||
f.setFormatter(new Formatter() {
|
||||
FileHandler fileHandler = new FileHandler(logFilePath, LOG_SIZE, LOG_FILE_COUNT);
|
||||
fileHandler.setEncoding(LOG_ENCODING);
|
||||
fileHandler.setFormatter(new Formatter() {
|
||||
@Override
|
||||
public String format(LogRecord record) {
|
||||
synchronized (fileHandlerLock) {
|
||||
return (new Date(record.getMillis())).toString() + " "
|
||||
+ record.getSourceClassName() + " "
|
||||
+ record.getSourceMethodName() + "\n"
|
||||
+ record.getLevel() + ": "
|
||||
+ this.formatMessage(record) + "\n";
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
case LOG_WITH_STACK_TRACES:
|
||||
f.setFormatter(new Formatter() {
|
||||
return fileHandler;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(String.format("Error initializing file handler for %s", logFilePath), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a custom file handler with a custom message formatter that
|
||||
* incldues stack traces.
|
||||
*
|
||||
* @param logDirectory The directory where the log files should reside.
|
||||
*
|
||||
* @return A custom file handler.
|
||||
*/
|
||||
private static FileHandler createFileHandlerWithTraces(String logDirectory) {
|
||||
String logFilePath = Paths.get(logDirectory, LOG_WITH_STACK_TRACES).toString();
|
||||
try {
|
||||
FileHandler fileHandler = new FileHandler(logFilePath, LOG_SIZE, LOG_FILE_COUNT);
|
||||
fileHandler.setEncoding(LOG_ENCODING);
|
||||
fileHandler.setFormatter(new Formatter() {
|
||||
@Override
|
||||
public String format(LogRecord record) {
|
||||
synchronized (fileHandlerLock) {
|
||||
if (record.getThrown() != null) {
|
||||
|
||||
StackTraceElement ele[] = record.getThrown().getStackTrace();
|
||||
String StackTrace = "";
|
||||
for (StackTraceElement ele1 : ele) {
|
||||
StackTrace += "\t" + ele1.toString() + "\n";
|
||||
String stackTrace = ""; //NON-NLS
|
||||
for (StackTraceElement traceElem : record.getThrown().getStackTrace()) {
|
||||
stackTrace += "\t" + traceElem.toString() + "\n"; //NON-NLS
|
||||
}
|
||||
|
||||
return (new Timestamp(record.getMillis())).toString() + " "
|
||||
+ record.getSourceClassName() + " "
|
||||
+ record.getSourceMethodName() + "\n"
|
||||
+ record.getLevel() + ": "
|
||||
+ this.formatMessage(record) + "\n"
|
||||
+ record.getThrown().toString() + ":\n"
|
||||
+ StackTrace
|
||||
+ "\n";
|
||||
return (new Timestamp(record.getMillis())).toString() + " " //NON-NLS
|
||||
+ record.getSourceClassName() + " " //NON-NLS
|
||||
+ record.getSourceMethodName() + "\n" //NON-NLS
|
||||
+ record.getLevel() + ": " //NON-NLS
|
||||
+ this.formatMessage(record) + "\n" //NON-NLS
|
||||
+ record.getThrown().toString() + ":\n" //NON-NLS
|
||||
+ stackTrace
|
||||
+ "\n"; //NON-NLS
|
||||
} else {
|
||||
return (new Timestamp(record.getMillis())).toString() + " "
|
||||
+ record.getSourceClassName() + " "
|
||||
+ record.getSourceMethodName() + "\n"
|
||||
+ record.getLevel() + ": "
|
||||
+ this.formatMessage(record) + "\n";
|
||||
}
|
||||
return (new Timestamp(record.getMillis())).toString() + " " //NON-NLS
|
||||
+ record.getSourceClassName() + " " //NON-NLS
|
||||
+ record.getSourceMethodName() + "\n" //NON-NLS
|
||||
+ record.getLevel() + ": " //NON-NLS
|
||||
+ this.formatMessage(record) + "\n"; //NON-NLS
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
return f;
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException("Error initializing " + fileName + " file handler", e); //NON-NLS
|
||||
return fileHandler;
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(String.format("Error initializing file handler for %s", logFilePath), ex); //NON-NLS
|
||||
}
|
||||
}
|
||||
|
||||
@ -105,63 +123,88 @@ public final class Logger extends java.util.logging.Logger {
|
||||
*
|
||||
* @param directoryPath The path to the desired log directory as a string.
|
||||
*/
|
||||
public static void setLogDirectory(String directoryPath) {
|
||||
if (null != directoryPath && !directoryPath.isEmpty()) {
|
||||
File directory = new File(directoryPath);
|
||||
if (directory.exists() && directory.canWrite()) {
|
||||
synchronized (fileHandlerLock) {
|
||||
userFriendlyLogFile.close();
|
||||
userFriendlyLogFile = createFileHandler(directoryPath, LOG_WITHOUT_STACK_TRACES);
|
||||
developersLogFile.close();
|
||||
developersLogFile = createFileHandler(directoryPath, LOG_WITH_STACK_TRACES);
|
||||
}
|
||||
}
|
||||
synchronized public static void setLogDirectory(String directoryPath) {
|
||||
/*
|
||||
* Create file handlers for the new directory and swap them into all of
|
||||
* the existing loggers using thread-safe Logger methods. The new
|
||||
* handlers are added before the old handlers so that no messages will
|
||||
* be lost, but this makes it possible for log messages to be written
|
||||
* via the old handlers if logging calls are interleaved with the
|
||||
* add/remove handler calls (currently, the base class handlers
|
||||
* collection is a CopyOnWriteArrayList).
|
||||
*/
|
||||
FileHandler newUserFriendlyHandler = createFileHandlerWithoutTraces(directoryPath);
|
||||
FileHandler newDeveloperFriendlyHandler = createFileHandlerWithTraces(directoryPath);
|
||||
for (Logger logger : namesToLoggers.values()) {
|
||||
logger.addHandler(newUserFriendlyHandler);
|
||||
logger.addHandler(newDeveloperFriendlyHandler);
|
||||
logger.removeHandler(userFriendlyHandler);
|
||||
logger.removeHandler(userFriendlyHandler);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close the old file handlers and save references to the new handlers
|
||||
* so they can be added to any new loggers. This swap is why this method
|
||||
* and the two overloads of getLogger() are synchronized, serializing
|
||||
* access to userFriendlyHandler and developerFriendlyHandler.
|
||||
*/
|
||||
userFriendlyHandler.close();
|
||||
userFriendlyHandler = newUserFriendlyHandler;
|
||||
developerFriendlyHandler.close();
|
||||
developerFriendlyHandler = newDeveloperFriendlyHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to retrieve a org.sleuthkit.autopsy.coreutils.Logger
|
||||
* instance derived from java.util.logging.Logger. Hides the base class
|
||||
* factory method.
|
||||
* Finds or creates a customized logger. Hides the base class factory
|
||||
* method.
|
||||
*
|
||||
* @param name A name for the logger. This should be a dot-separated name
|
||||
* and should normally be based on the package name or class
|
||||
* name.
|
||||
* @param name A name for the logger. This should normally be a
|
||||
* dot-separated name based on a package name or class name.
|
||||
*
|
||||
* @return org.sleuthkit.autopsy.coreutils.Logger instance
|
||||
*/
|
||||
public static Logger getLogger(String name) {
|
||||
return new Logger(name, null);
|
||||
synchronized public static Logger getLogger(String name) {
|
||||
return getLogger(name, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to retrieve a org.sleuthkit.autopsy.coreutils.Logger
|
||||
* instance derived from java.util.logging.Logger. Hides the base class
|
||||
* factory method.
|
||||
* Finds or creates a customized logger. Hides the base class factory
|
||||
* method.
|
||||
*
|
||||
* @param name A name for the logger. This should be a
|
||||
* dot-separated name and should normally be based
|
||||
* on the package name or class name.
|
||||
* @param resourceBundleName - name of ResourceBundle to be used for
|
||||
* @param name A name for the logger. This should normally be
|
||||
* a dot-separated name based on a package name or
|
||||
* class name.
|
||||
* @param resourceBundleName Name of ResourceBundle to be used for
|
||||
* localizing messages for this logger. May be
|
||||
* null if none of the messages require
|
||||
* localization.
|
||||
* null.
|
||||
*
|
||||
* @return org.sleuthkit.autopsy.coreutils.Logger instance
|
||||
*/
|
||||
public static Logger getLogger(String name, String resourceBundleName) {
|
||||
return new Logger(name, resourceBundleName);
|
||||
synchronized public static Logger getLogger(String name, String resourceBundleName) {
|
||||
if (!namesToLoggers.containsKey(name)) {
|
||||
Logger logger = new Logger(name, resourceBundleName);
|
||||
logger.addHandler(userFriendlyHandler);
|
||||
logger.addHandler(developerFriendlyHandler);
|
||||
namesToLoggers.put(name, logger);
|
||||
}
|
||||
return namesToLoggers.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a customized logger.
|
||||
*
|
||||
* @param name A name for the logger. This should normally be
|
||||
* a dot-separated name based on a package name or
|
||||
* class name.
|
||||
* @param resourceBundleName Name of ResourceBundle to be used for
|
||||
* localizing messages for this logger. May be
|
||||
* null.
|
||||
*/
|
||||
private Logger(String name, String resourceBundleName) {
|
||||
super(name, resourceBundleName);
|
||||
if (Version.getBuildType() == Version.Type.DEVELOPMENT) {
|
||||
super.addHandler(console);
|
||||
}
|
||||
synchronized (fileHandlerLock) {
|
||||
super.setUseParentHandlers(false);
|
||||
super.addHandler(userFriendlyLogFile);
|
||||
super.addHandler(developersLogFile);
|
||||
if (Version.getBuildType() == Version.Type.DEVELOPMENT) {
|
||||
super.addHandler(consoleHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ public class ModuleSettings {
|
||||
private final static String moduleDirPath = PlatformUtil.getUserConfigDirectory();
|
||||
public static final String DEFAULT_CONTEXT = "GeneralContext"; //NON-NLS
|
||||
public static final String MAIN_SETTINGS = "Case"; //NON-NLS
|
||||
public static final String CURRENT_CASE_TYPE = "Current_Case_Type"; //NON-NLS
|
||||
|
||||
/**
|
||||
* the constructor
|
||||
|
44
Core/src/org/sleuthkit/autopsy/coreutils/NetworkUtils.java
Normal file
44
Core/src/org/sleuthkit/autopsy/coreutils/NetworkUtils.java
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2012-2015 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.coreutils;
|
||||
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class NetworkUtils {
|
||||
|
||||
/**
|
||||
* Set the host name variable. Sometimes the network can be finicky, so the
|
||||
* answer returned by getHostName() could throw an exception or be null.
|
||||
* Have it read the environment variable if getHostName() is unsuccessful.
|
||||
*/
|
||||
public static String getLocalHostName() {
|
||||
String hostName = "";
|
||||
try {
|
||||
hostName = java.net.InetAddress.getLocalHost().getHostName();
|
||||
} catch (UnknownHostException ex) {
|
||||
// getLocalHost().getHostName() can fail in some situations.
|
||||
// Use environment variable if so.
|
||||
hostName = System.getenv("COMPUTERNAME");
|
||||
}
|
||||
if (hostName == null || hostName.isEmpty()) {
|
||||
hostName = System.getenv("COMPUTERNAME");
|
||||
}
|
||||
return hostName;
|
||||
}
|
||||
}
|
58
Core/src/org/sleuthkit/autopsy/coreutils/PathValidator.java
Normal file
58
Core/src/org/sleuthkit/autopsy/coreutils/PathValidator.java
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2013-2014 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.sleuthkit.autopsy.coreutils;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
|
||||
/**
|
||||
* Validates absolute path (e.g. to a data source or case output folder)
|
||||
* depending on case type.
|
||||
*/
|
||||
public final class PathValidator {
|
||||
|
||||
private static final Pattern driveLetterPattern = Pattern.compile("^[Cc]:.*$");
|
||||
|
||||
public static boolean isValid(String path, Case.CaseType caseType) {
|
||||
|
||||
if (caseType == Case.CaseType.MULTI_USER_CASE) {
|
||||
// check that path is not on "C:" drive
|
||||
if (pathOnCDrive(path)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// single user case - no validation needed
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file path contains drive letter defined by pattern.
|
||||
*
|
||||
* @param filePath Input file absolute path
|
||||
*
|
||||
* @return true if path matches the pattern, false otherwise.
|
||||
*/
|
||||
private static boolean pathOnCDrive(String filePath) {
|
||||
Matcher m = driveLetterPattern.matcher(filePath);
|
||||
return m.find();
|
||||
}
|
||||
}
|
97
Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java
Normal file
97
Core/src/org/sleuthkit/autopsy/coreutils/TimeStampUtils.java
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.coreutils;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Class offers utility functions to identify and process time stamped folders.
|
||||
*/
|
||||
public final class TimeStampUtils {
|
||||
|
||||
// Pattern to identify whether case name contains a generated time stamp.
|
||||
// Sample case name with time stamp: Case 1_2015_02_02_12_10_31 for case "Case 1"
|
||||
private static final Pattern timeStampPattern = Pattern.compile("\\d{4}_\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{2}$");
|
||||
private static final int LENGTH_OF_DATE_TIME_STAMP = 20; // length of the above time stamp
|
||||
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
|
||||
|
||||
/**
|
||||
* Checks whether a string ends with a time stamp defined by pattern.
|
||||
*
|
||||
* @param inputString Input string
|
||||
*
|
||||
* @return true if string ends with a time stamp, false otherwise.
|
||||
*/
|
||||
public static boolean endsWithTimeStamp(String inputString) {
|
||||
Matcher m = timeStampPattern.matcher(inputString);
|
||||
return m.find();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns length of time stamp string.
|
||||
*
|
||||
* @return length of time stamp string.
|
||||
*/
|
||||
public static int getTimeStampLength() {
|
||||
return LENGTH_OF_DATE_TIME_STAMP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a timestamp using the current time
|
||||
*
|
||||
* @return the timestamp as a String
|
||||
*/
|
||||
public static String createTimeStamp() {
|
||||
return dateFormat.format(Calendar.getInstance().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a timestamp if it exists
|
||||
*
|
||||
* @param input the String to remove the trailing timestamp from
|
||||
*
|
||||
* @return the String without timestamp
|
||||
*/
|
||||
public static String removeTimeStamp(String input) {
|
||||
String result = input;
|
||||
if (input != null && endsWithTimeStamp(input)) {
|
||||
result = input.substring(0, input.length() - getTimeStampLength());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the timestamp portion of the name passed in
|
||||
*
|
||||
* @param input the name to check for a timestamp
|
||||
*
|
||||
* @return the timestamp only, or empty String if none
|
||||
*/
|
||||
public static String getTimeStampOnly(String input) {
|
||||
String result = "";
|
||||
if (input != null && endsWithTimeStamp(input)) {
|
||||
result = input.substring(input.length() - getTimeStampLength(), input.length());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011 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.coreutils;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Formatter;
|
||||
import java.util.logging.LogRecord;
|
||||
|
||||
/*
|
||||
* Formatter to wrap another formatter and prepend a timestampe to each
|
||||
* formatted string Not currently used.
|
||||
*/
|
||||
class TimestampingFormatter extends Formatter {
|
||||
|
||||
Formatter original;
|
||||
DateFormat timestampFormat = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US);
|
||||
String lineSeparator = System.getProperty("line.separator");
|
||||
|
||||
TimestampingFormatter(Formatter original) {
|
||||
this.original = original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String format(LogRecord record) {
|
||||
long millis = record.getMillis();
|
||||
String timestamp = timestampFormat.format(new Date(millis));
|
||||
|
||||
return timestamp + lineSeparator + original.format(record);
|
||||
}
|
||||
}
|
308
Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java
Normal file
308
Core/src/org/sleuthkit/autopsy/coreutils/UNCPathUtilities.java
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 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.coreutils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class UNCPathUtilities {
|
||||
|
||||
private static Map<String, String> drives;
|
||||
private static final String MAPPED_DRIVES = "_mapped_drives.txt"; //NON-NLS
|
||||
private static final String TEMP_FOLDER = "TEMP";
|
||||
private static final String DATA_TRIGGER = "----------"; //NON-NLS
|
||||
private static final String OK_TXT = "OK"; //NON-NLS
|
||||
private static final String COLON = ":"; //NON-NLS
|
||||
private static final String UNC_PATH_START = "\\\\"; //NON-NLS
|
||||
private static final String C_DRIVE = "C:"; //NON-NLS
|
||||
private static final int DRIVE_LEN = 2;
|
||||
private static final int STARTING_OFFSET = 0;
|
||||
private static final int REPLACEMENT_SIZE = 2;
|
||||
private static final int FIRST_ITEM = 0;
|
||||
private final String nameString;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public UNCPathUtilities() {
|
||||
// get UUID for this instance
|
||||
this.nameString = UUID.randomUUID().toString();
|
||||
drives = getMappedDrives();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a passed in path to UNC if it is not already UNC.
|
||||
* The UNC path will end up in one of the following two forms:
|
||||
* \\hostname\somefolder\otherfolder or \\IP_ADDRESS\somefolder\otherfolder
|
||||
*
|
||||
* This is accomplished by checking the mapped drives list the operating
|
||||
* system maintains and substituting where required. If the drive of the
|
||||
* path passed in does not exist in the cached mapped drives list, you can
|
||||
* force a rescan of the mapped drives list with rescanDrives(), then call
|
||||
* this method again. This would be of use if the end user added a mapped
|
||||
* drive while your dialog was up, for example.
|
||||
*
|
||||
* @param inputPath a String of the path to convert
|
||||
*
|
||||
* @return returns a successfully converted inputPath or null if unable to
|
||||
* find a matching drive and convert it to UNC
|
||||
*/
|
||||
synchronized public String mappedDriveToUNC(String inputPath) {
|
||||
if (inputPath != null) {
|
||||
// If it is a C:, do not attempt to convert. This is for the single-user case.
|
||||
if (inputPath.toUpperCase().startsWith(C_DRIVE)) {
|
||||
return null;
|
||||
}
|
||||
if (false == isUNC(inputPath)) {
|
||||
String uncPath = null;
|
||||
try {
|
||||
String currentDrive = Paths.get(inputPath).getRoot().toString().substring(STARTING_OFFSET, REPLACEMENT_SIZE);
|
||||
String uncMapping = drives.get(currentDrive);
|
||||
if (uncMapping != null) {
|
||||
uncPath = uncMapping + inputPath.substring(REPLACEMENT_SIZE, inputPath.length());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// Didn't work. Skip it.
|
||||
}
|
||||
return uncPath;
|
||||
} else {
|
||||
return inputPath;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method converts a passed in path to UNC if it is not already UNC.
|
||||
* The UNC path will end up in one of the following two forms:
|
||||
* \\hostname\somefolder\otherfolder or \\IP_ADDRESS\somefolder\otherfolder
|
||||
*
|
||||
* This is accomplished by checking the mapped drives list the operating
|
||||
* system maintains and substituting where required. If the drive of the
|
||||
* path passed in does not exist in the cached mapped drives list, you can
|
||||
* force a rescan of the mapped drives list with rescanDrives(), then call
|
||||
* this method again. This would be of use if the end user added a mapped
|
||||
* drive while your dialog was up, for example.
|
||||
*
|
||||
* @param inputPath the path to convert
|
||||
*
|
||||
* @return returns a successfully converted inputPath or null if unable to
|
||||
* find a matching drive and convert it to UNC
|
||||
*/
|
||||
synchronized public Path mappedDriveToUNC(Path inputPath) {
|
||||
if (inputPath != null) {
|
||||
String uncPath = UNCPathUtilities.this.mappedDriveToUNC(inputPath.toString());
|
||||
if (uncPath == null) {
|
||||
return null;
|
||||
} else {
|
||||
return Paths.get(uncPath);
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the drive in the passed in path is a mapped drive.
|
||||
*
|
||||
* @param inputPath the Path to test.
|
||||
*
|
||||
* @return true if the passed in drive is mapped, false otherwise
|
||||
*/
|
||||
synchronized public boolean isDriveMapped(Path inputPath) {
|
||||
if (inputPath != null) {
|
||||
return isDriveMapped(inputPath.toString());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the drive in the passed in path is a mapped drive.
|
||||
*
|
||||
* @param inputPath the Path to test.
|
||||
*
|
||||
* @return true if the passed in drive is mapped, false otherwise
|
||||
*/
|
||||
synchronized public boolean isDriveMapped(String inputPath) {
|
||||
if (inputPath != null) {
|
||||
String shortenedPath = inputPath.substring(STARTING_OFFSET, DRIVE_LEN);
|
||||
for (String s : drives.keySet()) {
|
||||
if (shortenedPath.equals(s)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a UNC path that may have an IP address in it and converts it to
|
||||
* hostname, if it can resolve the hostname. Given
|
||||
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder
|
||||
* if the IP address 10.11.12.13 belongs to a machine with the hostname
|
||||
* TEDS_COMPUTER and the local machine is able to resolve the hostname.
|
||||
*
|
||||
* @param inputPath the path to convert to a hostname UNC path
|
||||
*
|
||||
* @return the successfully converted path or null if unable to resolve
|
||||
*/
|
||||
synchronized public Path ipToHostName(Path inputPath) {
|
||||
if (inputPath != null) {
|
||||
return Paths.get(ipToHostName(inputPath.toString()));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a UNC path that may have an IP address in it and converts it to
|
||||
* hostname, if it can resolve the hostname. Given
|
||||
* \\10.11.12.13\some\folder, the result will be \\TEDS_COMPUTER\some\folder
|
||||
* if the IP address 10.11.12.13 belongs to a machine with the hostname
|
||||
* TEDS_COMPUTER and the local machine is able to resolve the hostname.
|
||||
*
|
||||
* @param inputPath a String of the path to convert to a hostname UNC path
|
||||
*
|
||||
* @return the successfully converted path or null if unable to resolve
|
||||
*/
|
||||
synchronized public String ipToHostName(String inputPath) {
|
||||
if (inputPath != null) {
|
||||
String result = null;
|
||||
try {
|
||||
if (isUNC(Paths.get(inputPath))) {
|
||||
String potentialIP = Paths.get(inputPath.substring(REPLACEMENT_SIZE)).getName(FIRST_ITEM).toString();
|
||||
String hostname = InetAddress.getByName(potentialIP).getHostName();
|
||||
result = inputPath.replaceAll(potentialIP, hostname);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
// Could not resolve hostname for IP address, return null result
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a Path is UNC. It is considered UNC if it begins with \\
|
||||
*
|
||||
* @param inputPath the path to check
|
||||
*
|
||||
* @return true if the passed in Path is UNC, false otherwise
|
||||
*/
|
||||
synchronized public static boolean isUNC(Path inputPath) {
|
||||
if (inputPath != null) {
|
||||
return isUNC(inputPath.toString());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a String path is UNC. It is considered UNC if it begins with \\
|
||||
*
|
||||
* @param inputPath the String of the path to check
|
||||
*
|
||||
* @return true if the passed in Path is UNC, false otherwise
|
||||
*/
|
||||
synchronized public static boolean isUNC(String inputPath) {
|
||||
if (inputPath != null) {
|
||||
return inputPath.startsWith(UNC_PATH_START);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of mapped drives this class contains. This list is used
|
||||
* to resolve mappedDriveToUNC and isDriveMapped calls. This is useful to
|
||||
* call if the user has potentially added mapped drives to their system
|
||||
* after the module calling mappedDriveToUNC has already begun running. Note
|
||||
* this uses system I/O, so call it with some care.
|
||||
*
|
||||
*/
|
||||
synchronized public void rescanDrives() {
|
||||
drives = getMappedDrives();
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the list of mapped drives this class contains. The list is used
|
||||
* to resolve mappedDriveToUNC and isDriveMapped calls. Note this uses
|
||||
* system I/O, so call it with some care.
|
||||
*
|
||||
* @return the hashmap
|
||||
*/
|
||||
synchronized private Map<String, String> getMappedDrives() {
|
||||
Map<String, String> driveMap = new HashMap<>();
|
||||
File mappedDrive = Paths.get(System.getenv(TEMP_FOLDER), nameString + MAPPED_DRIVES).toFile();
|
||||
try {
|
||||
Files.deleteIfExists(mappedDrive.toPath());
|
||||
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "net", "use"); //NON-NLS
|
||||
builder.redirectOutput(mappedDrive);
|
||||
builder.redirectError(mappedDrive);
|
||||
Process p = builder.start(); // throws IOException
|
||||
p.waitFor(10, TimeUnit.SECONDS);
|
||||
try (Scanner scanner = new Scanner(mappedDrive)) {
|
||||
// parse the data and place it in the hashmap
|
||||
while (scanner.hasNext()) {
|
||||
String entry1 = scanner.next();
|
||||
if (entry1.startsWith(DATA_TRIGGER)) {
|
||||
continue;
|
||||
}
|
||||
String entry2 = scanner.next();
|
||||
if (entry2.startsWith(DATA_TRIGGER)) {
|
||||
continue;
|
||||
}
|
||||
String entry3 = scanner.next();
|
||||
if (entry3.startsWith(DATA_TRIGGER)) {
|
||||
continue;
|
||||
}
|
||||
scanner.nextLine();
|
||||
if (entry1.length() == DRIVE_LEN && !entry1.equals(OK_TXT) && entry1.endsWith(COLON)) {
|
||||
driveMap.put(entry1, entry2); // if there was no leading status, populate drive
|
||||
} else if (entry2.length() == DRIVE_LEN && entry2.endsWith(COLON)) {
|
||||
driveMap.put(entry2, entry3); // if there was a leading status, populate drive
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
// if we couldn't do it, no big deal
|
||||
Logger.getLogger(UNCPathUtilities.class.getName()).log(Level.WARNING, "Unable to parse 'net use' output", ex); //NON-NLS
|
||||
} finally {
|
||||
try {
|
||||
Files.deleteIfExists(mappedDrive.toPath());
|
||||
} catch (IOException ex) {
|
||||
// if we couldn't do it, no big deal
|
||||
}
|
||||
}
|
||||
return driveMap;
|
||||
}
|
||||
}
|
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