Merge remote-tracking branch 'upstream/develop' into Update-iLeapp-aLeapp

This commit is contained in:
Mark McKinnon 2023-06-06 14:01:37 -04:00
commit 2656cd618c
1199 changed files with 19968 additions and 2738 deletions

6
.gitattributes vendored
View File

@ -18,4 +18,8 @@ Doxyfile text
/KeywordSearch/solr/bin/autopsy-solr eol=lf
/KeywordSearch/solr/bin/init.d/solr eol=lf
/KeywordSearch/solr/bin/post eol=lf
/KeywordSearch/solr/bin/solr eol=lf
/KeywordSearch/solr/bin/solr eol=lf
# ensure properties files and xml files in the platform don't get changed during the build
/netbeans-plat/15/**/*.properties eol=lf
/netbeans-plat/15/**/*.xml eol=lf

224
.gitignore vendored
View File

@ -1,111 +1,113 @@
/dist/
/build/
/*/build/
*/nbproject/private/*
/nbproject/private/*
/apidiff_output/
/Core/release/
/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties
/Core/src/org/sleuthkit/autopsy/casemodule/docs/QuickStart.html
/Core/src/org/sleuthkit/autopsy/casemodule/docs/screenshot.png
/Core/src/org/sleuthkit/autopsy/datamodel/ranges.csv
/Core/build/
/Core/dist/
/Core/nbproject/*
/Core/test/qa-functional/data/*
!/Core/nbproject/project.xml
!/Core/nbproject/project.properties
/CoreLibs/release/
/CoreLibs/build/
/CoreLibs/dist/
/CoreLibs/nbproject/*
!/CoreLibs/nbproject/project.xml
!/CoreLibs/nbproject/project.properties
/CoreTestLibs/release/
/CoreTestLibs/build/
/CoreTestLibs/dist/
/Core/test/qa-functional/data/*
!/Core/test/qa-functional/data/PasswordDetection_img1_v1.img
/KeywordSearch/release/
/KeywordSearch/build/
/KeywordSearch/dist/
/KeywordSearch/nbproject/*
!/KeywordSearch/nbproject/project.xml
!/KeywordSearch/nbproject/project.properties
*/genfiles.properties
genfiles.properties
/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
/branding/build/
/branding/dist/
/branding/nbproject/*
!/branding/nbproject/project.xml
!/branding/nbproject/project.properties
/test/input/*
!/test/input/notablehashes.txt-md5.idx
!/test/input/notablekeywords.xml
!/test/input/NSRL.txt-md5.idx
/test/output/*
!/test/output/gold
/test/script/output_dir_link.txt
/test/output/gold/tmp
/test/script/ScriptLog.txt
/test/script/__pycache__/
/test/script/*.pyc
/test/script/DBDump-Diff.txt
/test/script/DBDump.txt
/test/script/SortedData-Diff.txt
/test/script/SortedData.txt
/test/script/myconfig.xml
/test/script/*/*.xml
/test/build/
/test/dist/
/test/nbproject/*
!/Testing/nbproject/project.xml
!/Testing/nbproject/project.properties
*~
/netbeans-plat
/docs/doxygen-user/user-docs
/docs/doxygen-dev/build-docs
/jdiff-javadocs/*
/jdiff-logs/*
/gen_version.txt
hs_err_pid*.log
.DS_Store
.*.swp
/Experimental/release/
/ImageGallery/release/
/thunderbirdparser/release/
/RecentActivity/release/
/CentralRepository/release/
/Tika/release
.idea/
*.iml
*.img
*.vhd
*.E01
/thirdparty/yara/yarabridge/yarabridge/x64/
/thirdparty/yara/yarabridge/yarabridge.VC.db
/thirdparty/yara/yarabridge/yarabridge.VC.VC.opendb
/thirdparty/yara/yarabridge/x64/
/thirdparty/yara/YaraWrapperTest/nbproject/private/
/thirdparty/yara/YaraWrapperTest/build/
/thirdparty/yara/YaraJNIWrapper/dist/
/thirdparty/yara/YaraJNIWrapper/build/
/thirdparty/yara/YaraJNIWrapper/nbproject/private/
/thirdparty/yara/yarabridge/.vs/
*/path_list.txt
/dist/
/build/
/*/build/
*/nbproject/private/*
/nbproject/private/*
/apidiff_output/
/Core/release/
/Core/src/org/sleuthkit/autopsy/coreutils/Version.properties
/Core/src/org/sleuthkit/autopsy/casemodule/docs/QuickStart.html
/Core/src/org/sleuthkit/autopsy/casemodule/docs/screenshot.png
/Core/src/org/sleuthkit/autopsy/datamodel/ranges.csv
/Core/build/
/Core/dist/
/Core/nbproject/*
/Core/test/qa-functional/data/*
!/Core/nbproject/project.xml
!/Core/nbproject/project.properties
/CoreLibs/release/
/CoreLibs/build/
/CoreLibs/dist/
/CoreLibs/nbproject/*
!/CoreLibs/nbproject/project.xml
!/CoreLibs/nbproject/project.properties
/CoreTestLibs/release/
/CoreTestLibs/build/
/CoreTestLibs/dist/
/Core/test/qa-functional/data/*
!/Core/test/qa-functional/data/PasswordDetection_img1_v1.img
/KeywordSearch/release/
/KeywordSearch/build/
/KeywordSearch/dist/
/KeywordSearch/nbproject/*
!/KeywordSearch/nbproject/project.xml
!/KeywordSearch/nbproject/project.properties
*/genfiles.properties
genfiles.properties
/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties
/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties
/branding/build/
/branding/dist/
/branding/nbproject/*
!/branding/nbproject/project.xml
!/branding/nbproject/project.properties
/test/input/*
!/test/input/notablehashes.txt-md5.idx
!/test/input/notablekeywords.xml
!/test/input/NSRL.txt-md5.idx
/test/output/*
!/test/output/gold
/test/script/output_dir_link.txt
/test/output/gold/tmp
/test/script/ScriptLog.txt
/test/script/__pycache__/
/test/script/*.pyc
/test/script/DBDump-Diff.txt
/test/script/DBDump.txt
/test/script/SortedData-Diff.txt
/test/script/SortedData.txt
/test/script/myconfig.xml
/test/script/*/*.xml
/test/build/
/test/dist/
/test/nbproject/*
!/Testing/nbproject/project.xml
!/Testing/nbproject/project.properties
*~
/netbeans-plat/*
# include netbeans platform 15 because it doesn't seem to download consistently or is being updated
!/netbeans-plat/15
/docs/doxygen-user/user-docs
/docs/doxygen-dev/build-docs
/jdiff-javadocs/*
/jdiff-logs/*
/gen_version.txt
hs_err_pid*.log
.DS_Store
.*.swp
/Experimental/release/
/ImageGallery/release/
/thunderbirdparser/release/
/RecentActivity/release/
/CentralRepository/release/
/Tika/release
.idea/
*.iml
*.img
*.vhd
*.E01
/thirdparty/yara/yarabridge/yarabridge/x64/
/thirdparty/yara/yarabridge/yarabridge.VC.db
/thirdparty/yara/yarabridge/yarabridge.VC.VC.opendb
/thirdparty/yara/yarabridge/x64/
/thirdparty/yara/YaraWrapperTest/nbproject/private/
/thirdparty/yara/YaraWrapperTest/build/
/thirdparty/yara/YaraJNIWrapper/dist/
/thirdparty/yara/YaraJNIWrapper/build/
/thirdparty/yara/YaraJNIWrapper/nbproject/private/
/thirdparty/yara/yarabridge/.vs/
*/path_list.txt

View File

@ -1,5 +1,4 @@
language: java
sudo: required
jobs:
include:
@ -9,63 +8,61 @@ jobs:
osx_image: xcode12.2
env:
global:
- TSK_HOME=$TRAVIS_BUILD_DIR/sleuthkit/sleuthkit
global:
- TSK_HOME=$TRAVIS_BUILD_DIR/sleuthkit/sleuthkit
addons:
apt:
update: true
packages:
- testdisk
- libafflib-dev
- libewf-dev
- libpq-dev
- autopoint
- libsqlite3-dev
- ant
- ant-optional
- libcppunit-dev
- wget
- openjdk-8-jdk
- openjfx=8u161-b12-1ubuntu2
- libopenjfx-java=8u161-b12-1ubuntu2
- libopenjfx-jni=8u161-b12-1ubuntu2
- testdisk
- libafflib-dev
- libewf-dev
- libpq-dev
- autopoint
- libsqlite3-dev
- ant
- ant-optional
- libcppunit-dev
- wget
homebrew:
update: true
packages:
- ant
- wget
- libpq
- libewf
- gettext
- cppunit
- afflib
- testdisk
- ant
- wget
- libpq
- libewf
- gettext
- cppunit
- afflib
- testdisk
python:
- "2.7"
- 2.7
before_install:
- git clone https://github.com/sleuthkit/sleuthkit.git sleuthkit/sleuthkit
- python setupSleuthkitBranch.py
- git clone https://github.com/sleuthkit/sleuthkit.git sleuthkit/sleuthkit
- python setupSleuthkitBranch.py
install:
- pushd sleuthkit/sleuthkit && ./travis_install_libs.sh && popd
- pushd sleuthkit/sleuthkit && ./travis_install_libs.sh && popd
before_script:
- if [ $TRAVIS_OS_NAME = linux ]; then
sudo update-alternatives --set java /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java;
sudo update-alternatives --set javac /usr/lib/jvm/java-8-openjdk-amd64/bin/javac;
export PATH=/usr/bin:$PATH;
unset JAVA_HOME;
wget -q -O - https://download.bell-sw.com/pki/GPG-KEY-bellsoft | sudo apt-key add -;
echo "deb [arch=amd64] https://apt.bell-sw.com/ stable main" | sudo tee /etc/apt/sources.list.d/bellsoft.list;
sudo apt-get update;
sudo apt-get install bellsoft-java17-full;
export PATH=/usr/bin:$PATH;
export JAVA_HOME=/usr/lib/jvm/bellsoft-java17-full-amd64;
fi
- if [ $TRAVIS_OS_NAME = osx ]; then
brew uninstall java --force;
brew cask uninstall java --force;
brew tap homebrew/cask-versions;
brew cask install corretto8;
export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home;
- if [ $TRAVIS_OS_NAME = osx ]; then
brew uninstall java --force --ignore-dependencies;
brew cask uninstall java --force;
brew tap bell-sw/liberica;
brew install --cask liberica-jdk17-full;
export JAVA_HOME=/Library/Java/JavaVirtualMachines/liberica-jdk-17-full.jdk/Contents/Home;
fi
- java -version
script: ./travis_build.sh
script: ./travis_build.sh

View File

@ -11,12 +11,9 @@ 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_66 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.
1a) Download and install 64-bit JDK version 17 with JavaFX.
Autopsy has been used and tested with the following OpenJDK build
(https://github.com/ojdkbuild/ojdkbuild/releases/tag/java-1.8.0-openjdk-1.8.0.222-1.b10).
Autopsy has been used and tested with liberica java which can be downloaded from here: https://bell-sw.com/pages/downloads/.
1b) Ensure that JDK_HOME is set to the root JDK directory.

View File

@ -134,8 +134,8 @@
<property environment="env"/>
<copy file="${env.TSK_HOME}/bindings/java/dist/sleuthkit-${TSK_VERSION}.jar"
tofile="${ext.dir}/sleuthkit-${TSK_VERSION}.jar"/>
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.36.0.3.jar"
tofile="${ext.dir}/sqlite-jdbc-3.36.0.3.jar"/>
<copy file="${env.TSK_HOME}/bindings/java/lib/sqlite-jdbc-3.42.0.0.jar"
tofile="${ext.dir}/sqlite-jdbc-3.42.0.0.jar"/>
<copy file="${env.TSK_HOME}/bindings/java/lib/postgresql-42.3.5.jar"
tofile="${ext.dir}/postgresql-42.3.5.jar"/>
<copy file="${env.TSK_HOME}/bindings/java/lib/c3p0-0.9.5.5.jar"
@ -310,41 +310,19 @@
(i.e. https://stackoverflow.com/questions/219585/including-all-the-jars-in-a-directory-within-the-java-classpath).
This solution involves taking the initial module.run.classpath property and simplifying it to the directories containing jars
(i.e. instead of “/dir/lib1.jar:/dir/lib2.jar:/dir/lib3.jar” it becomes “/dir/*” ).
More information on module.run.classpath can be found in “netbeans-plat\11.3\harness\README” and it appears that
“netbeans-plat\11.3\harness\build.xml:build-init target is in charge of setting the module.run.classpath variable.
More information on module.run.classpath can be found in “netbeans-plat\15\harness\README” and it appears that
“netbeans-plat\15\harness\build.xml:build-init target is in charge of setting the module.run.classpath variable.
More information in Jira: 6970.
-->
<target name="unit-test-path-simplification" depends="projectized-common.test-init">
<property name="unit-test-path-simplification.dir.path" value="${thirdparty.dir}/ClasspathSimplification/target"/>
<property name="unit-test-path-simplification.jar.path" value="${unit-test-path-simplification.dir.path}/ClasspathSimplification-1.0-jar-with-dependencies.jar"/>
<taskdef name="classpathsimplify" classname="org.sleuthkit.autopsy.classpathsimplification.ClasspathSimplification" classpath="${unit-test-path-simplification.jar.path}"/>
<sequential>
<script language="javascript">
<![CDATA[
var moduleRunClasspath = project.getProperty("module.run.classpath");
var directories = [];
// searches for jar file parent directories with path separators of \ or /
var individualPathRegex = /^\s*(.+?[\\\/])[^\\\/]+?\.jar\s*$/i;
// split on ':' but not 'C:\'
var classPathRegex = /((C:\\)?.+?)(:|$)/gi;
var match;
while((match = classPathRegex.exec(moduleRunClasspath)) !== null) {
var thisPath = match[1];
var pathMatch = thisPath.match(individualPathRegex);
// find unique matches
if (pathMatch && directories.indexOf(pathMatch[1]) < 0) {
directories.push(pathMatch[1]);
}
}
// suffix with *
for (var i = 0; i < directories.length; i++) {
directories[i] = directories[i] + "*";
}
// set project property
project.setNewProperty("test.unit.abbreviatedModuleRunClassPath", directories.join(":"));
]]>
</script>
<classpathsimplify classpath="${module.run.classpath}" outputprop="test.unit.abbreviatedModuleRunClassPath" />
<!--grab properties from common.xml:test-init so that "test.unit.run.cp" can be properly formed-->
<property name="build.test.unit.dir" location="${build.dir}/test/unit"/>
<property name="build.test.unit.classes.dir" location="${build.test.unit.dir}/classes"/>

View File

@ -40,6 +40,10 @@
<!-- for handling diffs -->
<dependency conf="core->default" org="io.github.java-diff-utils" name="java-diff-utils" rev="4.11"/>
<!-- JAXB -->
<dependency conf="core->default" org="javax.xml.bind" name="jaxb-api" rev="2.3.1"/>
<dependency conf="core->default" org="org.glassfish.jaxb" name="jaxb-runtime" rev="2.3.3"/>
<dependency conf="core->default" org="org.icepdf.os" name="icepdf-viewer" rev="6.2.2">
<!-- get the new latest batik items below, override bouncy castle -->

View File

@ -1,16 +1,16 @@
cluster.path=\
${nbplatform.active.dir}/platform
disabled.modules=\
org.netbeans.api.visual,\
org.netbeans.core.execution,\
org.netbeans.core.multiview,\
org.netbeans.libs.jsr223,\
org.netbeans.modules.autoupdate.services,\
org.netbeans.modules.autoupdate.ui,\
org.netbeans.modules.core.kit,\
org.netbeans.modules.favorites,\
org.openide.compat,\
org.openide.execution,\
org.openide.options,\
org.openide.util.enumerations
nbplatform.active=default
# cluster.path=\
# ${nbplatform.active.dir}/platform
# disabled.modules=\
# org.netbeans.api.visual,\
# org.netbeans.core.execution,\
# org.netbeans.core.multiview,\
# org.netbeans.libs.jsr223,\
# org.netbeans.modules.autoupdate.services,\
# org.netbeans.modules.autoupdate.ui,\
# org.netbeans.modules.core.kit,\
# org.netbeans.modules.favorites,\
# org.openide.compat,\
# org.openide.execution,\
# org.openide.options,\
# org.openide.util.enumerations
# nbplatform.active=default

View File

@ -1,7 +1,13 @@
file.reference.activemq-all-5.16.4.jar=release/modules/ext/activemq-all-5.16.4.jar
file.reference.audience-annotations-0.12.0.jar=release/modules/ext/audience-annotations-0.12.0.jar
file.reference.batik-awt-util-1.14.jar=release/modules/ext/batik-awt-util-1.14.jar
file.reference.batik-constants-1.14.jar=release/modules/ext/batik-constants-1.14.jar
file.reference.batik-css-1.14.jar=release/modules/ext/batik-css-1.14.jar
file.reference.batik-dom-1.14.jar=release/modules/ext/batik-dom-1.14.jar
file.reference.batik-ext-1.14.jar=release/modules/ext/batik-ext-1.14.jar
file.reference.batik-i18n-1.14.jar=release/modules/ext/batik-i18n-1.14.jar
file.reference.batik-parser-1.14.jar=release/modules/ext/batik-parser-1.14.jar
file.reference.batik-shared-resources-1.14.jar=release/modules/ext/batik-shared-resources-1.14.jar
file.reference.batik-svg-dom-1.14.jar=release/modules/ext/batik-svg-dom-1.14.jar
file.reference.batik-svggen-1.14.jar=release/modules/ext/batik-svggen-1.14.jar
file.reference.batik-util-1.14.jar=release/modules/ext/batik-util-1.14.jar
@ -9,6 +15,7 @@ file.reference.batik-xml-1.14.jar=release/modules/ext/batik-xml-1.14.jar
file.reference.bcpkix-jdk15on-1.70.jar=release/modules/ext/bcpkix-jdk15on-1.70.jar
file.reference.bcprov-ext-jdk15on-1.70.jar=release/modules/ext/bcprov-ext-jdk15on-1.70.jar
file.reference.bcprov-jdk15on-1.70.jar=release/modules/ext/bcprov-jdk15on-1.70.jar
file.reference.bcutil-jdk15on-1.70.jar=release/modules/ext/bcutil-jdk15on-1.70.jar
file.reference.c3p0-0.9.5.5.jar=release/modules/ext/c3p0-0.9.5.5.jar
file.reference.checker-qual-3.12.0.jar=release/modules/ext/checker-qual-3.12.0.jar
file.reference.commons-dbcp2-2.9.0.jar=release/modules/ext/commons-dbcp2-2.9.0.jar
@ -26,13 +33,19 @@ file.reference.failureaccess-1.0.1.jar=release/modules/ext/failureaccess-1.0.1.j
file.reference.guava-31.1-jre.jar=release/modules/ext/guava-31.1-jre.jar
file.reference.icepdf-core-6.2.2.jar=release/modules/ext/icepdf-core-6.2.2.jar
file.reference.icepdf-viewer-6.2.2.jar=release/modules/ext/icepdf-viewer-6.2.2.jar
file.reference.istack-commons-runtime-3.0.11.jar=release/modules/ext/istack-commons-runtime-3.0.11.jar
file.reference.j2objc-annotations-1.3.jar=release/modules/ext/j2objc-annotations-1.3.jar
file.reference.jackcess-4.0.1.jar=release/modules/ext/jackcess-4.0.1.jar
file.reference.jackcess-encrypt-4.0.1.jar=release/modules/ext/jackcess-encrypt-4.0.1.jar
file.reference.jai_core-1.1.3.jar=release/modules/ext/jai_core-1.1.3.jar
file.reference.jai_imageio-1.1.jar=release/modules/ext/jai_imageio-1.1.jar
file.reference.jakarta.activation-1.2.2.jar=release/modules/ext/jakarta.activation-1.2.2.jar
file.reference.jakarta.xml.bind-api-2.3.3.jar=release/modules/ext/jakarta.xml.bind-api-2.3.3.jar
file.reference.java-diff-utils-4.11.jar=release/modules/ext/java-diff-utils-4.11.jar
file.reference.javax.activation-api-1.2.0.jar=release/modules/ext/javax.activation-api-1.2.0.jar
file.reference.javax.ws.rs-api-2.1.1.jar=release/modules/ext/javax.ws.rs-api-2.1.1.jar
file.reference.jaxb-api-2.3.1.jar=release/modules/ext/jaxb-api-2.3.1.jar
file.reference.jaxb-runtime-2.3.3.jar=release/modules/ext/jaxb-runtime-2.3.3.jar
file.reference.jdom-2.0.5.jar=release/modules/ext/jdom-2.0.5.jar
file.reference.jfreechart-1.5.3.jar=release/modules/ext/jfreechart-1.5.3.jar
file.reference.jgraphx-4.2.2.jar=release/modules/ext/jgraphx-4.2.2.jar
@ -62,6 +75,7 @@ file.reference.okhttp-2.7.5.jar=release/modules/ext/okhttp-2.7.5.jar
file.reference.okio-1.6.0.jar=release/modules/ext/okio-1.6.0.jar
file.reference.postgresql-42.3.5.jar=release/modules/ext/postgresql-42.3.5.jar
file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
file.reference.serializer-2.7.2.jar=release/modules/ext/serializer-2.7.2.jar
file.reference.sevenzipjbinding-AllPlatforms.jar=release/modules/ext/sevenzipjbinding-AllPlatforms.jar
file.reference.sevenzipjbinding.jar=release/modules/ext/sevenzipjbinding.jar
file.reference.sleuthkit-4.12.0.jar=release/modules/ext/sleuthkit-4.12.0.jar
@ -69,12 +83,17 @@ file.reference.sleuthkit-caseuco-4.12.0.jar=release/modules/ext/sleuthkit-caseuc
file.reference.snakeyaml-1.30.jar=release/modules/ext/snakeyaml-1.30.jar
file.reference.SparseBitSet-1.1.jar=release/modules/ext/SparseBitSet-1.1.jar
file.reference.spotbugs-annotations-4.6.0.jar=release/modules/ext/spotbugs-annotations-4.6.0.jar
file.reference.sqlite-jdbc-3.36.0.3.jar=release/modules/ext/sqlite-jdbc-3.36.0.3.jar
file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar
file.reference.txw2-2.3.3.jar=release/modules/ext/txw2-2.3.3.jar
file.reference.xalan-2.7.2.jar=release/modules/ext/xalan-2.7.2.jar
file.reference.xml-apis-1.4.01.jar=release/modules/ext/xml-apis-1.4.01.jar
file.reference.xml-apis-ext-1.3.04.jar=release/modules/ext/xml-apis-ext-1.3.04.jar
file.reference.xmlgraphics-commons-2.6.jar=release/modules/ext/xmlgraphics-commons-2.6.jar
file.reference.xmpcore-6.1.11.jar=release/modules/ext/xmpcore-6.1.11.jar
file.reference.YaraJNIWrapper.jar=release/modules/ext/YaraJNIWrapper.jar
file.reference.zookeeper-3.8.0.jar=release/modules/ext/zookeeper-3.8.0.jar
file.reference.zookeeper-jute-3.8.0.jar=release/modules/ext/zookeeper-jute-3.8.0.jar
javac.source=1.8
javac.source=17
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/

View File

@ -12,7 +12,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.28.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -20,7 +20,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
<specification-version>1.64</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -28,7 +28,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -36,7 +36,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.6.1</specification-version>
<specification-version>1.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -48,13 +48,31 @@
<implementation-version/>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.core.multitabs</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<implementation-version/>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.core.windows</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
<implementation-version/>
</run-dependency>
</dependency>
<dependency>
<code-name-base>org.netbeans.modules.options.api</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.26.1</specification-version>
<specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -63,7 +81,7 @@
<compile-dependency/>
<run-dependency>
<release-version>2</release-version>
<specification-version>2.25.1</specification-version>
<specification-version>2.53</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -72,7 +90,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.35.1</specification-version>
<specification-version>1.66</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -80,7 +98,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.14.1</specification-version>
<specification-version>1.44</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -88,7 +106,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.20.1</specification-version>
<specification-version>1.51</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -96,7 +114,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.25.1</specification-version>
<specification-version>1.59</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -104,7 +122,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.36.1</specification-version>
<specification-version>1.74</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -112,7 +130,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.26.1</specification-version>
<specification-version>6.56</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -120,7 +138,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.46.1</specification-version>
<specification-version>7.85</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -128,7 +146,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.25.1</specification-version>
<specification-version>7.63</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -136,7 +154,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.45.1</specification-version>
<specification-version>6.79</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -144,23 +162,23 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.62.1</specification-version>
<specification-version>9.29</specification-version>
</run-dependency>
</dependency>
<dependency>
<!-- <dependency>
<code-name-base>org.openide.filesystems.compat8</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.7.1</specification-version>
<specification-version>9.26</specification-version>
</run-dependency>
</dependency>
</dependency> -->
<dependency>
<code-name-base>org.openide.filesystems.nb</code-name-base>
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.7.1</specification-version>
<specification-version>9.27</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -168,7 +186,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.63.2</specification-version>
<specification-version>7.87</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -176,7 +194,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.32.1</specification-version>
<specification-version>7.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -184,7 +202,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.28.1</specification-version>
<specification-version>7.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -192,7 +210,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.49.1</specification-version>
<specification-version>6.85</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -200,7 +218,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.25.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -208,7 +226,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.15.1</specification-version>
<specification-version>8.51</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -216,7 +234,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.4.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -224,7 +242,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.55.1</specification-version>
<specification-version>6.94</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -362,10 +380,34 @@
<runtime-relative-path>ext/batik-awt-util-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-awt-util-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-constants-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-constants-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-css-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-css-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-dom-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-dom-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-ext-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-ext-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-i18n-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-i18n-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-parser-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-parser-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-shared-resources-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-shared-resources-1.14.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/batik-svg-dom-1.14.jar</runtime-relative-path>
<binary-origin>release/modules/ext/batik-svg-dom-1.14.jar</binary-origin>
@ -394,6 +436,10 @@
<runtime-relative-path>ext/bcprov-jdk15on-1.70.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcprov-jdk15on-1.70.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcutil-jdk15on-1.70.jar</runtime-relative-path>
<binary-origin>release/modules/ext/bcutil-jdk15on-1.70.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/c3p0-0.9.5.5.jar</runtime-relative-path>
<binary-origin>release/modules/ext/c3p0-0.9.5.5.jar</binary-origin>
@ -462,6 +508,10 @@
<runtime-relative-path>ext/icepdf-viewer-6.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/icepdf-viewer-6.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/istack-commons-runtime-3.0.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/istack-commons-runtime-3.0.11.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/j2objc-annotations-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/j2objc-annotations-1.3.jar</binary-origin>
@ -482,14 +532,34 @@
<runtime-relative-path>ext/jai_imageio-1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jai_imageio-1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jakarta.activation-1.2.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jakarta.activation-1.2.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jakarta.xml.bind-api-2.3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jakarta.xml.bind-api-2.3.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/java-diff-utils-4.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/java-diff-utils-4.11.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.activation-api-1.2.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/javax.activation-api-1.2.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/javax.ws.rs-api-2.1.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/javax.ws.rs-api-2.1.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jaxb-api-2.3.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jaxb-api-2.3.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jaxb-runtime-2.3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jaxb-runtime-2.3.3.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>
@ -506,6 +576,10 @@
<runtime-relative-path>ext/jsoup-1.14.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jsoup-1.14.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jsr305-3.0.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jsr305-3.0.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jutf7-1.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jutf7-1.0.0.jar</binary-origin>
@ -602,6 +676,10 @@
<runtime-relative-path>ext/Rejistry-1.1-SNAPSHOT.jar</runtime-relative-path>
<binary-origin>release/modules/ext/Rejistry-1.1-SNAPSHOT.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/serializer-2.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/serializer-2.7.2.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>
@ -631,8 +709,28 @@
<binary-origin>release/modules/ext/spotbugs-annotations-4.6.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sqlite-jdbc-3.36.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.36.0.3.jar</binary-origin>
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/txw2-2.3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/txw2-2.3.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xalan-2.7.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xalan-2.7.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xml-apis-1.4.01.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xml-apis-1.4.01.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xml-apis-ext-1.3.04.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xml-apis-ext-1.3.04.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmlgraphics-commons-2.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/xmlgraphics-commons-2.6.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/xmpcore-6.1.11.jar</runtime-relative-path>

View File

@ -45,7 +45,6 @@
<Group type="102" alignment="1" attributes="0">
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
<Component id="detailsPanel" max="32767" attributes="0"/>
<EmptySpace min="0" pref="0" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -87,7 +86,6 @@
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="&lt;CaseDetailsPanel.casePanel.border.title&gt;">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CaseDetailsPanel.casePanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
</TitledBorder>
</Border>
</Property>
@ -328,7 +326,6 @@
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="&lt;CaseDetailsPanel.examinerPanel.border.title&gt;">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CaseDetailsPanel.examinerPanel.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
</TitledBorder>
</Border>
</Property>
@ -506,7 +503,6 @@
<Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo">
<TitledBorder title="&lt;CaseDetailsPanel.pnOrganization.border.title&gt;">
<ResourceString PropertyName="titleX" bundle="org/sleuthkit/autopsy/casemodule/Bundle.properties" key="CaseDetailsPanel.pnOrganization.border.title" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
<Font PropertyName="font" name="Tahoma" size="12" style="0"/>
</TitledBorder>
</Border>
</Property>

View File

@ -182,7 +182,7 @@ final class CaseDetailsPanel extends javax.swing.JPanel {
jTextArea1.setRows(5);
jScrollPane1.setViewportView(jTextArea1);
casePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.casePanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N
casePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.casePanel.border.title"))); // NOI18N
caseNameLabel.setText(org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.caseNameLabel.text")); // NOI18N
caseNameLabel.setMaximumSize(new java.awt.Dimension(82, 14));
@ -295,7 +295,7 @@ final class CaseDetailsPanel extends javax.swing.JPanel {
.addGap(6, 6, 6))
);
examinerPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.examinerPanel.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N
examinerPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.examinerPanel.border.title"))); // NOI18N
lbNotesLabel.setText(org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.lbNotesLabel.text")); // NOI18N
lbNotesLabel.setMaximumSize(new java.awt.Dimension(82, 14));
@ -381,7 +381,7 @@ final class CaseDetailsPanel extends javax.swing.JPanel {
.addGap(6, 6, 6))
);
pnOrganization.setBorder(javax.swing.BorderFactory.createTitledBorder(null, org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.pnOrganization.border.title"), javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N
pnOrganization.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.pnOrganization.border.title"))); // NOI18N
lbOrganizationNameLabel.setText(org.openide.util.NbBundle.getMessage(CaseDetailsPanel.class, "CaseDetailsPanel.lbOrganizationNameLabel.text")); // NOI18N
lbOrganizationNameLabel.setMaximumSize(new java.awt.Dimension(82, 14));
@ -484,8 +484,7 @@ final class CaseDetailsPanel extends javax.swing.JPanel {
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
.addGap(0, 0, 0)
.addComponent(detailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGap(0, 0, 0))
.addComponent(detailsPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents

View File

@ -163,7 +163,9 @@ final public class VisualizationPanel extends JPanel {
this.relationshipBrowser = relationshipBrowser;
initComponents();
//initialize invisible JFXPanel that is used to show JFXNotifications over this window.
notificationsJFXPanel.setScene(new Scene(new Pane()));
Platform.runLater(() -> {
notificationsJFXPanel.setScene(new Scene(new Pane()));
});
graph = new CommunicationsGraph(pinnedAccountModel, lockedVertexModel);

View File

@ -20,6 +20,7 @@ package org.sleuthkit.autopsy.contentviewers;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.image.Image;
@ -87,7 +88,12 @@ final class JavaFxAppSink extends AppSink {
fxImageView = new ImageView(); // Will hold the current video frame.
BorderPane borderpane = new BorderPane(fxImageView); // Center and size ImageView.
Scene scene = new Scene(borderpane); // Root of the JavaFX tree.
target.setScene(scene);
// Although the documentation for JFXPanel.setScene() claims that it
// can be called on either the EDT or the JavaFX thread, with JavaFX 11
// it doesn't work unless you call it on the JavaFX application thread.
Platform.runLater(() -> {
target.setScene(scene);
});
// Bind size of image to that of scene, while keeping proportions
fxImageView.fitWidthProperty().bind(scene.widthProperty());

View File

@ -19,7 +19,7 @@
.label {
-fx-wrap-text:true;
-fx-text-fill: red;
-fx-text-fill: #ff0000;
-fx-font-size: 2em;
}
@ -28,6 +28,6 @@
}
.masker-pane .masker-text {
-fx-text-fill: white;
-fx-text-fill: #ffffff;
-fx-font-size: 1.5em;
}

View File

@ -18,7 +18,9 @@
*/
package org.sleuthkit.autopsy.contentviewers.imagetagging;
import com.sun.javafx.event.EventDispatchChainImpl;
// TODO: See JIRA-6693
//import com.sun.javafx.event.EventDispatchChainImpl;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
@ -46,7 +48,7 @@ import org.sleuthkit.autopsy.casemodule.services.contentviewertags.ContentViewer
public final class ImageTag extends Group {
// Used to tell the 8 edit handles to hide if this tag is no longer selected
private final EventDispatchChainImpl ALL_CHILDREN;
// private final EventDispatchChainImpl ALL_CHILDREN;
private final PhysicalTag physicalTag;
@ -57,13 +59,13 @@ public final class ImageTag extends Group {
private final ContentViewerTag<ImageTagRegion> appTag;
public ImageTag(ContentViewerTag<ImageTagRegion> contentViewerTag, ImageView image) {
ALL_CHILDREN = new EventDispatchChainImpl();
// ALL_CHILDREN = new EventDispatchChainImpl();
this.appTag = contentViewerTag;
this.getChildren().addListener((ListChangeListener<Node>) change -> {
change.next();
change.getAddedSubList().forEach((node) -> ALL_CHILDREN.append(node.getEventDispatcher()));
});
// this.getChildren().addListener((ListChangeListener<Node>) change -> {
// change.next();
// change.getAddedSubList().forEach((node) -> ALL_CHILDREN.append(node.getEventDispatcher()));
// });
ImageTagRegion details = contentViewerTag.getDetails();
physicalTag = new PhysicalTag(details);
@ -120,8 +122,8 @@ public final class ImageTag extends Group {
Tooltip.install(this, new Tooltip(contentViewerTag.getContentTag()
.getName().getDisplayName()));
this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
this.addEventHandler(ImageTagControls.FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
// this.addEventHandler(ImageTagControls.NOT_FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
// this.addEventHandler(ImageTagControls.FOCUSED, event -> ALL_CHILDREN.dispatchEvent(event));
}
/**

View File

@ -18,11 +18,11 @@
*/
package org.sleuthkit.autopsy.contentviewers.imagetagging;
import com.sun.javafx.event.EventDispatchChainImpl;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javafx.event.Event;
import javafx.event.EventDispatchChain;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
@ -41,7 +41,8 @@ import javafx.scene.input.MouseEvent;
*/
public final class ImageTagsGroup extends Group {
private final EventDispatchChainImpl NO_OP_CHAIN = new EventDispatchChainImpl();
// TODO: See JIRA-6693
// private final EventDispatchChain NO_OP_CHAIN = new EventDispatchChainImpl();
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private volatile ImageTag currentFocus;
@ -50,10 +51,10 @@ public final class ImageTagsGroup extends Group {
//Reset focus of current selection if the back drop has focus.
backDrop.setOnMousePressed((mouseEvent) -> {
if (currentFocus != null) {
currentFocus.getEventDispatcher().dispatchEvent(
new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
}
// if (currentFocus != null) {
// currentFocus.getEventDispatcher().dispatchEvent(
// new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
// }
this.pcs.firePropertyChange(new PropertyChangeEvent(this,
ImageTagControls.NOT_FOCUSED.getName(), currentFocus, null));
@ -130,7 +131,7 @@ public final class ImageTagsGroup extends Group {
* @param n
*/
private void resetFocus(ImageTag n) {
n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
// n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.NOT_FOCUSED), NO_OP_CHAIN);
this.pcs.firePropertyChange(new PropertyChangeEvent(this, ImageTagControls.NOT_FOCUSED.getName(), n, null));
}
@ -146,7 +147,7 @@ public final class ImageTagsGroup extends Group {
resetFocus(currentFocus);
}
n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.FOCUSED), NO_OP_CHAIN);
// n.getEventDispatcher().dispatchEvent(new Event(ImageTagControls.FOCUSED), NO_OP_CHAIN);
this.pcs.firePropertyChange(new PropertyChangeEvent(this, ImageTagControls.FOCUSED.getName(), currentFocus, n));
currentFocus = n;

View File

@ -11,7 +11,7 @@ OpenIDE-Module-Short-Description=Autopsy Core Module
org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml
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 JavaFX installed (OpenJFX 8).
Installer.errorInitJavafx.details=\ Some features will not be available. Check that you have JavaFX installed (OpenJFX 11).
ServicesMonitor.failedService.notify.title=Service Is Down
ServicesMonitor.failedService.notify.msg=Connection to {0} is down
ServicesMonitor.restoredService.notify.title=Service Is Up

View File

@ -15,7 +15,7 @@ OpenIDE-Module-Short-Description=Autopsy Core Module
org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml
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 JavaFX installed (OpenJFX 8).
Installer.errorInitJavafx.details=\ Some features will not be available. Check that you have JavaFX installed (OpenJFX 11).
ServicesMonitor.failedService.notify.title=Service Is Down
ServicesMonitor.failedService.notify.msg=Connection to {0} is down
ServicesMonitor.restoredService.notify.title=Service Is Up

View File

@ -263,8 +263,15 @@ public class Installer extends ModuleInstall {
//initialize java fx if exists
System.setProperty("javafx.macosx.embedded", "true");
try {
// Due to a lingering issue https://bugs.openjdk.org/browse/JDK-8223377 where glass.dll from java 8 gets loaded instead of the java 17 one.
String javaLibraryPath = "java.library.path";
String jvmBinPathStr = Paths.get(System.getProperty("java.home"), "bin").toAbsolutePath().toString();
String path = System.getProperty(javaLibraryPath);
System.setProperty(javaLibraryPath, StringUtils.isBlank(path) ? jvmBinPathStr : jvmBinPathStr + File.pathSeparator + path);
// Creating a JFXPanel initializes JavaFX
JFXPanel panel = new JFXPanel();
new JFXPanel();
Platform.setImplicitExit(false);
javaFxInit = true;
} catch (UnsatisfiedLinkError | NoClassDefFoundError | Exception e) {

View File

@ -26,12 +26,12 @@
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="860" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="955" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane1" alignment="0" pref="620" max="32767" attributes="0"/>
<Component id="jScrollPane1" alignment="0" pref="699" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -244,7 +244,7 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="23" max="-2" attributes="0"/>
<Component id="memFieldValidationLabel" min="-2" pref="478" max="-2" attributes="0"/>
<EmptySpace pref="12" max="32767" attributes="0"/>
<EmptySpace pref="117" max="32767" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="18" max="-2" attributes="0"/>
@ -521,7 +521,7 @@
</Group>
</Group>
</Group>
<EmptySpace pref="164" max="32767" attributes="0"/>
<EmptySpace pref="269" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -635,11 +635,14 @@
</TitledBorder>
</Border>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 175]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[33, 100]"/>
<Dimension value="[300, 175]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[100, 150]"/>
<Dimension value="[300, 175]"/>
</Property>
</Properties>
<Constraints>
@ -678,7 +681,15 @@
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/corecomponents/Bundle.properties" key="AutopsyOptionsPanel.sizingTextPane.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="autoscrolls" type="boolean" value="false"/>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[453, 220]"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[453, 220]"/>
</Property>
<Property name="selectionStart" type="int" value="0"/>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_VariableLocal" type="java.lang.Boolean" value="true"/>

View File

@ -1016,7 +1016,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addGroup(runtimePanelLayout.createSequentialGroup()
.addGap(23, 23, 23)
.addComponent(memFieldValidationLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(12, Short.MAX_VALUE))
.addContainerGap(117, Short.MAX_VALUE))
.addGroup(runtimePanelLayout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(solrJVMHeapWarning, javax.swing.GroupLayout.PREFERRED_SIZE, 331, javax.swing.GroupLayout.PREFERRED_SIZE)
@ -1149,7 +1149,7 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
.addComponent(tempCustomField, javax.swing.GroupLayout.PREFERRED_SIZE, 459, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tempDirectoryBrowseButton)))))
.addContainerGap(164, Short.MAX_VALUE))
.addContainerGap(269, Short.MAX_VALUE))
);
tempDirectoryPanelLayout.setVerticalGroup(
tempDirectoryPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
@ -1179,8 +1179,9 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
tempDirectoryPanel.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.tempDirectoryPanel.AccessibleContext.accessibleName")); // NOI18N
rdpPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.rdpPanel.border.title"))); // NOI18N
rdpPanel.setMinimumSize(new java.awt.Dimension(33, 100));
rdpPanel.setPreferredSize(new java.awt.Dimension(100, 150));
rdpPanel.setMaximumSize(new java.awt.Dimension(300, 175));
rdpPanel.setMinimumSize(new java.awt.Dimension(300, 175));
rdpPanel.setPreferredSize(new java.awt.Dimension(300, 175));
rdpPanel.setLayout(new java.awt.GridBagLayout());
sizingScrollPane.setBorder(null);
@ -1188,7 +1189,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
sizingTextPane.setEditable(false);
sizingTextPane.setBorder(null);
sizingTextPane.setText(org.openide.util.NbBundle.getMessage(AutopsyOptionsPanel.class, "AutopsyOptionsPanel.sizingTextPane.text")); // NOI18N
sizingTextPane.setAutoscrolls(false);
sizingTextPane.setMinimumSize(new java.awt.Dimension(453, 220));
sizingTextPane.setOpaque(false);
sizingTextPane.setPreferredSize(new java.awt.Dimension(453, 220));
sizingTextPane.setSelectionStart(0);
sizingScrollPane.setViewportView(sizingTextPane);
gridBagConstraints = new java.awt.GridBagConstraints();
@ -1220,11 +1225,11 @@ final class AutopsyOptionsPanel extends javax.swing.JPanel {
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 860, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 955, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 620, Short.MAX_VALUE)
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 699, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents

View File

@ -23,16 +23,19 @@ import java.awt.Insets;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.stream.Stream;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.plaf.FontUIResource;
import org.netbeans.spi.sendopts.OptionProcessor;
import org.netbeans.swing.tabcontrol.plaf.DefaultTabbedContainerUI;
import org.openide.modules.ModuleInstall;
@ -128,7 +131,7 @@ public class Installer extends ModuleInstall {
UIManager.put("OptionPane.warningIcon", warningIcon);
UIManager.put("OptionPane.questionIcon", questionIcon);
UIManager.put("OptionPane.informationIcon", informationIcon);
if (System.getProperty("os.name").toLowerCase().contains("mac")) { //NON-NLS
setUnixLookAndFeel();
setModuleSettings("false");

View File

@ -6,8 +6,11 @@
</Component>
</NonVisualComponents>
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[727, 520]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[727, 495]"/>
<Dimension value="[727, 520]"/>
</Property>
</Properties>
<AuxValues>
@ -30,7 +33,7 @@
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="viewPreferencesScrollPane" alignment="0" max="32767" attributes="0"/>
<Component id="viewPreferencesScrollPane" alignment="0" pref="520" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
@ -40,8 +43,11 @@
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[727, 500]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[727, 493]"/>
<Dimension value="[727, 500]"/>
</Property>
</Properties>

View File

@ -187,10 +187,12 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
currentSessionSettingsPanel = new javax.swing.JPanel();
hideRejectedResultsCheckbox = new javax.swing.JCheckBox();
setPreferredSize(new java.awt.Dimension(727, 495));
setMinimumSize(new java.awt.Dimension(727, 520));
setPreferredSize(new java.awt.Dimension(727, 520));
viewPreferencesScrollPane.setBorder(null);
viewPreferencesScrollPane.setPreferredSize(new java.awt.Dimension(727, 493));
viewPreferencesScrollPane.setMinimumSize(new java.awt.Dimension(727, 500));
viewPreferencesScrollPane.setPreferredSize(new java.awt.Dimension(727, 500));
viewPreferencesPanel.setPreferredSize(new java.awt.Dimension(727, 492));
@ -502,7 +504,7 @@ public class ViewPreferencesPanel extends JPanel implements OptionsPanel {
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(viewPreferencesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(viewPreferencesScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 520, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents

View File

@ -18,7 +18,6 @@
*/
package org.sleuthkit.autopsy.coreutils;
import com.sun.javafx.PlatformUtil;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@ -28,6 +27,7 @@ import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.logging.Level;
import org.apache.commons.lang3.SystemUtils;
import org.sleuthkit.autopsy.core.UserPreferences;
/**
@ -371,7 +371,7 @@ public final class ExecUtil {
return;
}
if (PlatformUtil.isWindows()) {
if (SystemUtils.IS_OS_WINDOWS) {
try {
Win32Process parentProcess = new Win32Process(process);
List<Win32Process> children = parentProcess.getChildren();

View File

@ -20,25 +20,31 @@ package org.sleuthkit.autopsy.coreutils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryUsage;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import javax.swing.filechooser.FileSystemView;
import org.apache.commons.io.FilenameUtils;
import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.ptql.ProcessFinder;
import org.apache.commons.io.IOUtils;
import org.openide.modules.InstalledFileLocator;
import org.openide.modules.Places;
import org.openide.util.NbBundle;
@ -60,7 +66,6 @@ public class PlatformUtil {
public static final String OS_VERSION_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.verUnknown");
public static final String OS_ARCH_UNKNOWN = NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.archUnknown");
private static volatile long pid = -1;
private static volatile Sigar sigar = null;
private static volatile MemoryMXBean memoryManager = null;
/**
@ -238,7 +243,7 @@ public class PlatformUtil {
public static String getModuleConfigDirectory() {
return Paths.get(getUserConfigDirectory(), "ModuleConfig").toString();
}
/**
* Get log directory path
*
@ -504,25 +509,8 @@ public class PlatformUtil {
* @return PID of this process or -1 if it couldn't be determined
*/
public static synchronized long getPID() {
if (pid != -1) {
return pid;
}
try {
if (sigar == null) {
sigar = org.sleuthkit.autopsy.corelibs.SigarLoader.getSigar();
}
if (sigar != null) {
pid = sigar.getPid();
} else {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getPID.sigarNotInit.msg"));
}
} catch (Exception e) {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getPID.gen.msg", e.toString()));
}
return pid;
// taken from https://stackoverflow.com/a/7303433/2375948
return ProcessHandle.current().pid();
}
/**
@ -536,56 +524,123 @@ public class PlatformUtil {
* @return PID of a java process or -1 if it couldn't be determined
*/
public static synchronized long getJavaPID(String sigarSubQuery) {
long jpid = -1;
final String sigarQuery = "State.Name.sw=java," + sigarSubQuery; //NON-NLS
try {
if (sigar == null) {
sigar = org.sleuthkit.autopsy.corelibs.SigarLoader.getSigar();
}
if (sigar != null) {
ProcessFinder finder = new ProcessFinder(sigar);
jpid = finder.findSingleProcess(sigarQuery);
} else {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getJavaPID.sigarNotInit.msg"));
}
} catch (Exception e) {
System.out.println(
NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getJavaPID.gen.msg", sigarQuery, e.toString()));
long[] pids = getJavaPIDs(sigarSubQuery);
return pids == null || pids.length < 1
? -1
: pids[0];
}
/**
* Performs a simple conversion of a sql like statement to regex replacing
* '%' and '_' in a like statement with regex equivalents.
*
* @param originalLikeStatement The original like statement.
* @return The equivalent regex string.
*/
private static String convertSqlLikeToRegex(String originalLikeStatement) {
if (originalLikeStatement == null) {
return "";
}
return jpid;
Map<Character, String> likeEscapeSequences = new HashMap<>() {
{
put('%', ".*");
put('_', ".");
}
};
String regexQuoted = Pattern.quote(originalLikeStatement);
char[] charArr = regexQuoted.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < charArr.length; i++) {
char curChar = charArr[i];
String regexReplacement = likeEscapeSequences.get(curChar);
if (regexReplacement == null) {
sb.append(curChar);
} else {
Character nextChar = charArr.length > i + 1 ? charArr[i + 1] : null;
if (nextChar != null && curChar == nextChar) {
sb.append(curChar);
i++;
} else {
sb.append(regexReplacement);
}
}
}
return sb.toString();
}
/**
* Query and get PIDs of another java processes matching a query
*
* @param sigarSubQuery a sigar subquery to identify a java processes among
* other java processes, for example, by class name,
* use: Args.*.eq=org.jboss.Main more examples here:
* http://support.hyperic.com/display/SIGAR/PTQL
* @param argsSubQuery A like query for command line arguments
*
* @return array of PIDs of a java processes matching the query or null if
* it couldn't be determined
*/
public static synchronized long[] getJavaPIDs(String sigarSubQuery) {
long[] jpids = null;
final String sigarQuery = "State.Name.sw=java," + sigarSubQuery; //NON-NLS
public static synchronized long[] getJavaPIDs(String argsSubQuery) {
try {
if (sigar == null) {
sigar = org.sleuthkit.autopsy.corelibs.SigarLoader.getSigar();
}
if (sigar != null) {
ProcessFinder finder = new ProcessFinder(sigar);
jpids = finder.find(sigarQuery);
} else {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getJavaPIDs.sigarNotInit"));
}
} catch (Exception e) {
System.out.println(
NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getJavaPIDs.gen.msg", sigarQuery, e.toString()));
}
return jpids;
if (isWindowsOS()) {
ProcessBuilder pb = new ProcessBuilder("wmic process where \"name='java.exe' AND commandline LIKE '%" + argsSubQuery + "%'\" get ProcessID");
String output = IOUtils.toString(pb.start().getInputStream(), StandardCharsets.UTF_8);
String[] lines = output.split("\\r?\\n");
return Stream.of(lines).skip(1).map(ln -> {
if (ln == null || ln.trim().isEmpty()) {
return null;
}
try {
return Long.parseLong(ln.trim());
} catch (NumberFormatException ex) {
return null;
}
})
.filter(num -> num != null)
.mapToLong(l -> l)
.toArray();
} else {
String sigarRegexQuery = convertSqlLikeToRegex(argsSubQuery);
ProcessBuilder pb = new ProcessBuilder("sh", "-c", "ps -ef | grep -E 'java.*" + sigarRegexQuery + ".*'");
String output = IOUtils.toString(pb.start().getInputStream(), StandardCharsets.UTF_8);
List<String> lines = Arrays.asList(output.split("\\r?\\n"));
if (lines.size() > 0) {
// ignore last one as it will be the same as this command
lines.remove(lines.size() - 1);
}
return lines.stream().skip(1).map(ln -> {
if (ln == null || ln.trim().isEmpty()) {
return null;
}
ln = ln.trim();
String[] pieces = ln.split("\\s*");
if (pieces.length < 2) {
return null;
}
try {
return Long.parseLong(pieces[1]);
} catch (NumberFormatException ex) {
return null;
}
})
.filter(num -> num != null)
.mapToLong(l -> l)
.toArray();
}
} catch (IOException ex) {
System.out.println("An exception occurred while fetching java pids with query: " + argsSubQuery + " with IO Exception: " + ex.getMessage());
ex.printStackTrace();
return null;
}
}
/**
@ -594,20 +649,16 @@ public class PlatformUtil {
* @param pid pid of the process to kill
*/
public static synchronized void killProcess(long pid) {
try {
if (sigar == null) {
sigar = org.sleuthkit.autopsy.corelibs.SigarLoader.getSigar();
}
if (sigar != null) {
sigar.kill(pid, 9);
} else {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.killProcess.sigarNotInit.msg"));
}
} catch (Exception e) {
System.out.println(
NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.killProcess.gen.msg", pid, e.toString()));
}
String cmd = isWindowsOS()
? "taskkill /F /PID " + pid
: "kill " + pid;
try {
Runtime.getRuntime().exec(cmd);
} catch (IOException ex) {
System.out.println("An exception occurred while killing process pid: " + pid);
ex.printStackTrace();
}
}
/**
@ -616,23 +667,8 @@ public class PlatformUtil {
* @return virt memory used in bytes or -1 if couldn't be queried
*/
public static synchronized long getProcessVirtualMemoryUsed() {
long virtMem = -1;
try {
if (sigar == null) {
sigar = org.sleuthkit.autopsy.corelibs.SigarLoader.getSigar();
}
if (sigar == null || getPID() == -1) {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getProcVmUsed.sigarNotInit.msg"));
return -1;
}
virtMem = sigar.getProcMem(getPID()).getSize();
} catch (Exception e) {
System.out.println(NbBundle.getMessage(PlatformUtil.class, "PlatformUtil.getProcVmUsed.gen.msg", e.toString()));
}
return virtMem;
// taken from https://stackoverflow.com/a/17376879/2375948
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
/**

View File

@ -55,6 +55,11 @@ import org.xml.sax.SAXException;
*/
public class XMLUtil {
static {
// this is to ensure using xalan for the transformer factory: https://stackoverflow.com/a/64364531/2375948
System.setProperty("javax.xml.transform.TransformerFactory","com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
}
private static DocumentBuilder getDocumentBuilder() throws ParserConfigurationException {
// See JIRA-6958 for details about class loading and jaxb.
ClassLoader original = Thread.currentThread().getContextClassLoader();

View File

@ -515,7 +515,7 @@ public class Artifacts {
} catch (TskCoreException ex) {
logger.log(Level.WARNING, "Error getting child count", ex); //NON-NLS
}
super.setDisplayName(this.baseName + " \u200E(\u200E" + this.childCount + ")\u200E");
super.setDisplayName(this.baseName + " (" + this.childCount + ")");
}
}

View File

@ -329,7 +329,7 @@ public class Tags implements AutopsyVisitableItem {
} catch (TskCoreException | NoCurrentCaseException ex) {
Logger.getLogger(TagNameNode.class.getName()).log(Level.SEVERE, "Failed to get tags count for " + tagName.getDisplayName() + " tag name", ex); //NON-NLS
}
setDisplayName(TagUtils.getDecoratedTagDisplayName(tagName) + " \u200E(\u200E" + tagsCount + ")\u200E");
setDisplayName(TagUtils.getDecoratedTagDisplayName(tagName) + " (" + tagsCount + ")");
}
@Override

View File

@ -84,12 +84,7 @@ class DirectoryTreeFilterNode extends FilterNode {
try {
int numVisibleChildren = getVisibleChildCount(file);
/*
* Left-to-right marks here are necessary to keep the count
* and parens together for mixed right-to-left and
* left-to-right names.
*/
name = name + " \u200E(\u200E" + numVisibleChildren + ")\u200E"; //NON-NLS
name = name + " (" + numVisibleChildren + ")"; //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting children count to display for file: " + file, ex); //NON-NLS
@ -98,7 +93,7 @@ class DirectoryTreeFilterNode extends FilterNode {
BlackboardArtifact artifact = ((BlackboardArtifactNode) orig).getArtifact();
try {
int numAttachments = artifact.getChildrenCount();
name = name + " \u200E(\u200E" + numAttachments + ")\u200E"; //NON-NLS
name = name + " (" + numAttachments + ")"; //NON-NLS
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error getting chidlren count for atifact: " + artifact, ex); //NON-NLS
}

View File

@ -23,8 +23,8 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import javax.xml.bind.DatatypeConverter;
import java.util.Arrays;
import org.apache.commons.codec.binary.Hex;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModule;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress;
@ -250,8 +250,8 @@ public class DataSourceIntegrityIngestModule implements DataSourceIngestModule {
}
// Produce the final hashes
for (HashData hashData : hashDataList) {
hashData.calculatedHash = DatatypeConverter.printHexBinary(hashData.digest.digest()).toLowerCase();
for(HashData hashData: hashDataList) {
hashData.calculatedHash = Hex.encodeHexString(hashData.digest.digest()).toLowerCase();
logger.log(Level.INFO, "Hash calculated from {0}: {1}", new Object[]{imgName, hashData.calculatedHash}); //NON-NLS
}

View File

@ -22,7 +22,8 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JOptionPane;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.modules.filetypeid.FileType.Signature;
@ -101,7 +102,7 @@ class AddFileTypeSignaturePanel extends javax.swing.JPanel {
this.offsetTextField.setText(toEdit.getOffset() + "");
if (Signature.Type.RAW == toEdit.getType()) {
this.signatureTypeComboBox.setSelectedIndex(0);
this.signatureTextField.setText(DatatypeConverter.printHexBinary(toEdit.getSignatureBytes()));
this.signatureTextField.setText(Hex.encodeHexString(toEdit.getSignatureBytes()));
} else {
this.signatureTypeComboBox.setSelectedIndex(1);
try {
@ -146,8 +147,8 @@ class AddFileTypeSignaturePanel extends javax.swing.JPanel {
if (FileType.Signature.Type.RAW == sigType) {
try {
sigString = sigString.replaceAll("\\s", ""); //NON-NLS
signatureBytes = DatatypeConverter.parseHexBinary(sigString);
} catch (IllegalArgumentException ex) {
signatureBytes = Hex.decodeHex(sigString);
} catch (DecoderException ex) {
JOptionPane.showMessageDialog(this,
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidRawSignatureBytes.message"),
NbBundle.getMessage(FileTypeIdGlobalSettingsPanel.class, "FileTypeIdGlobalSettingsPanel.JOptionPane.invalidSignatureBytes.title"),

View File

@ -28,6 +28,8 @@ import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.DatatypeConverter;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.openide.util.io.NbObjectInputStream;
import org.openide.util.io.NbObjectOutputStream;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
@ -166,7 +168,7 @@ final class CustomFileTypesManager {
/*
* Add type for gzip.
*/
byteArray = DatatypeConverter.parseHexBinary("1F8B"); //NON-NLS
byteArray = Hex.decodeHex("1F8B"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("application/x-gzip", signatureList); //NON-NLS
@ -175,7 +177,7 @@ final class CustomFileTypesManager {
/*
* Add type for wk1.
*/
byteArray = DatatypeConverter.parseHexBinary("0000020006040600080000000000"); //NON-NLS
byteArray = Hex.decodeHex("0000020006040600080000000000"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("application/x-123", signatureList); //NON-NLS
@ -184,7 +186,7 @@ final class CustomFileTypesManager {
/*
* Add type for Radiance images.
*/
byteArray = DatatypeConverter.parseHexBinary("233F52414449414E43450A");//NON-NLS
byteArray = Hex.decodeHex("233F52414449414E43450A");//NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("image/vnd.radiance", signatureList); //NON-NLS
@ -193,7 +195,7 @@ final class CustomFileTypesManager {
/*
* Add type for dcx images.
*/
byteArray = DatatypeConverter.parseHexBinary("B168DE3A"); //NON-NLS
byteArray = Hex.decodeHex("B168DE3A"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("image/x-dcx", signatureList); //NON-NLS
@ -210,7 +212,7 @@ final class CustomFileTypesManager {
/*
* Add type for pict images.
*/
byteArray = DatatypeConverter.parseHexBinary("001102FF"); //NON-NLS
byteArray = Hex.decodeHex("001102FF"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 522L));
fileType = new FileType("image/x-pict", signatureList); //NON-NLS
@ -251,7 +253,7 @@ final class CustomFileTypesManager {
/*
* Add type for tga.
*/
byteArray = DatatypeConverter.parseHexBinary("54525545564953494F4E2D5846494C452E00"); //NON-NLS
byteArray = Hex.decodeHex("54525545564953494F4E2D5846494C452E00"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 17, false));
fileType = new FileType("image/x-tga", signatureList); //NON-NLS
@ -311,7 +313,7 @@ final class CustomFileTypesManager {
* Add type for .tec files with leading End Of Image marker (JFIF
* JPEG)
*/
byteArray = DatatypeConverter.parseHexBinary("FFD9FFD8"); //NON-NLS
byteArray = Hex.decodeHex("FFD9FFD8"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("image/jpeg", signatureList); //NON-NLS
@ -321,7 +323,7 @@ final class CustomFileTypesManager {
* Add type for Windows NT registry files with leading End Of Image marker (JFIF
* JPEG)
*/
byteArray = DatatypeConverter.parseHexBinary("72656766"); //NON-NLS
byteArray = Hex.decodeHex("72656766"); //NON-NLS
signatureList.clear();
signatureList.add(new Signature(byteArray, 0L));
fileType = new FileType("application/x.windows-registry", signatureList); //NON-NLS
@ -345,9 +347,10 @@ final class CustomFileTypesManager {
fileType = new FileType("application/x-vhd", signatureList); //NON-NLS
autopsyDefinedFileTypes.add(fileType);
} catch (IllegalArgumentException ex) {
} catch (DecoderException ex) {
/*
* parseHexBinary() throws this if the argument passed in is not hex
* decodeHex() throws this if an odd number of characters or illegal
* characters are supplied
*/
throw new CustomFileTypesException("Error creating Autopsy defined custom file types", ex); //NON-NLS
}
@ -442,7 +445,7 @@ final class CustomFileTypesManager {
}
}
return fileTypes;
} catch (IOException | ParserConfigurationException | SAXException ex) {
} catch (IOException | ParserConfigurationException | SAXException | DecoderException ex) {
throw new CustomFileTypesException(String.format("Failed to read ssettings from %s", filePath), ex); //NON-NLS
}
}
@ -459,7 +462,7 @@ final class CustomFileTypesManager {
* @throws NumberFormatException if there is a problem parsing the file
* type.
*/
private static FileType parseFileType(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
private static FileType parseFileType(Element fileTypeElem) throws DecoderException, NumberFormatException {
String mimeType = parseMimeType(fileTypeElem);
Signature signature = parseSignature(fileTypeElem);
// File type definitions in the XML file were written prior to the
@ -487,7 +490,7 @@ final class CustomFileTypesManager {
*
* @return The signature.
*/
private static Signature parseSignature(Element fileTypeElem) throws IllegalArgumentException, NumberFormatException {
private static Signature parseSignature(Element fileTypeElem) throws DecoderException, NumberFormatException {
NodeList signatureElems = fileTypeElem.getElementsByTagName(SIGNATURE_TAG_NAME);
Element signatureElem = (Element) signatureElems.item(0);
@ -495,18 +498,18 @@ final class CustomFileTypesManager {
Signature.Type signatureType = Signature.Type.valueOf(sigTypeAttribute);
String sigBytesString = getChildElementTextContent(signatureElem, BYTES_TAG_NAME);
byte[] signatureBytes = DatatypeConverter.parseHexBinary(sigBytesString);
byte[] signatureBytes = Hex.decodeHex(sigBytesString);
Element offsetElem = (Element) signatureElem.getElementsByTagName(OFFSET_TAG_NAME).item(0);
String offsetString = offsetElem.getTextContent();
long offset = DatatypeConverter.parseLong(offsetString);
long offset = Long.parseLong(offsetString);
boolean isRelativeToStart;
String relativeString = offsetElem.getAttribute(RELATIVE_ATTRIBUTE);
if (null == relativeString || relativeString.equals("")) {
isRelativeToStart = true;
} else {
isRelativeToStart = DatatypeConverter.parseBoolean(relativeString);
isRelativeToStart = Boolean.parseBoolean(relativeString);
}
return new Signature(signatureBytes, offset, signatureType, isRelativeToStart);

View File

@ -28,7 +28,7 @@ import java.util.List;
import java.util.Objects;
import java.util.logging.Level;
import javax.swing.JOptionPane;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.codec.binary.Hex;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.AbstractFile;
@ -389,7 +389,7 @@ class FileType implements Serializable {
public String toString() {
String signatureBytesString;
if (Signature.Type.RAW == this.getType()) {
signatureBytesString = DatatypeConverter.printHexBinary(this.getSignatureBytes());
signatureBytesString = Hex.encodeHexString(this.getSignatureBytes());
signatureBytesString = "0x" + signatureBytesString;
} else {
try {

View File

@ -24,14 +24,14 @@
<Group type="102" alignment="0" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="statusMessageLabel" max="32767" attributes="0"/>
<Component id="statusMessageLabel" pref="474" max="32767" attributes="0"/>
<Component id="reportProgressBar" alignment="0" max="32767" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="reportLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="separationLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="pathLabel" pref="548" max="32767" attributes="0"/>
<Component id="pathLabel" max="32767" attributes="0"/>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
@ -86,11 +86,32 @@
</Property>
</Properties>
</Component>
<Component class="javax.swing.JLabel" name="statusMessageLabel">
<Component class="javax.swing.JTextArea" name="statusMessageLabel">
<Properties>
<Property name="editable" type="boolean" value="false"/>
<Property name="background" type="java.awt.Color" editor="org.netbeans.modules.form.RADConnectionPropertyEditor">
<Connection code="null" type="code"/>
</Property>
<Property name="lineWrap" type="boolean" value="true"/>
<Property name="rows" type="int" value="5"/>
<Property name="tabSize" type="int" value="4"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/report/Bundle.properties" key="ReportProgressPanel.statusMessageLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="wrapStyleWord" type="boolean" value="true"/>
<Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor">
<Border info="null"/>
</Property>
<Property name="maximumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[2147483647, 80]"/>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[101, 80]"/>
</Property>
<Property name="opaque" type="boolean" value="false"/>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[2147483647, 80]"/>
</Property>
</Properties>
</Component>
</SubComponents>

View File

@ -41,6 +41,8 @@ public class ReportProgressPanel extends javax.swing.JPanel {
private static final Color GREEN = new Color(50, 205, 50);
private static final Color RED = new Color(178, 34, 34);
private volatile ReportStatus status;
private static final int MAX_STATUS_LENGTH = 500;
private static final String ELIPSIS = "...";
/**
* Used by a report generation module to communicate report generation
@ -75,6 +77,15 @@ public class ReportProgressPanel extends javax.swing.JPanel {
return displayName;
}
}
private void setStatusText(String message) {
if (message == null) {
message = "";
} else if (message.length() > MAX_STATUS_LENGTH) {
message = message.substring(0, MAX_STATUS_LENGTH) + ELIPSIS;
}
this.statusMessageLabel.setText(message);
}
/**
* Constructs a panel used by report generation module to show progress.
@ -83,7 +94,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
initComponents();
reportProgressBar.setIndeterminate(true);
reportProgressBar.setMaximum(100);
statusMessageLabel.setText(Bundle.ReportProgressPanel_progress_queuing());
setStatusText(Bundle.ReportProgressPanel_progress_queuing());
status = ReportStatus.QUEUING;
reportLabel.setText("");
pathLabel.setText(""); //NON-NLS
@ -174,7 +185,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
*/
public void start() {
EventQueue.invokeLater(() -> {
statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text"));
setStatusText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.start.progress.text"));
status = ReportStatus.RUNNING;
});
}
@ -242,7 +253,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
public void updateStatusLabel(String statusMessage) {
EventQueue.invokeLater(() -> {
if (status != ReportStatus.CANCELED) {
statusMessageLabel.setText(statusMessage);
setStatusText(statusMessage);
}
});
}
@ -284,7 +295,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
ReportStatus oldValue = status;
status = ReportStatus.COMPLETE;
statusMessageLabel.setForeground(Color.BLACK);
statusMessageLabel.setText(statusMessage);
setStatusText(statusMessage);
reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true);
reportProgressBar.setForeground(GREEN);
@ -296,7 +307,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
ReportStatus oldValue = status;
status = ReportStatus.ERROR;
statusMessageLabel.setForeground(RED);
statusMessageLabel.setText(statusMessage);
setStatusText(statusMessage);
reportProgressBar.setValue(reportProgressBar.getMaximum());
reportProgressBar.setStringPainted(true);
reportProgressBar.setForeground(RED);
@ -334,7 +345,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
reportProgressBar.setString(ReportStatus.CANCELED.getDisplayName());
firePropertyChange(ReportStatus.CANCELED.toString(), oldValue, status);
statusMessageLabel.setForeground(RED);
statusMessageLabel.setText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.cancel.procLbl.text"));
setStatusText(NbBundle.getMessage(this.getClass(), "ReportProgressPanel.cancel.procLbl.text"));
break;
}
}
@ -368,7 +379,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
reportLabel = new javax.swing.JLabel();
pathLabel = new javax.swing.JLabel();
separationLabel = new javax.swing.JLabel();
statusMessageLabel = new javax.swing.JLabel();
statusMessageLabel = new javax.swing.JTextArea();
setMinimumSize(new java.awt.Dimension(486, 68));
@ -380,7 +391,18 @@ public class ReportProgressPanel extends javax.swing.JPanel {
org.openide.awt.Mnemonics.setLocalizedText(separationLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.separationLabel.text")); // NOI18N
org.openide.awt.Mnemonics.setLocalizedText(statusMessageLabel, org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.statusMessageLabel.text")); // NOI18N
statusMessageLabel.setEditable(false);
statusMessageLabel.setBackground(null);
statusMessageLabel.setLineWrap(true);
statusMessageLabel.setRows(5);
statusMessageLabel.setTabSize(4);
statusMessageLabel.setText(org.openide.util.NbBundle.getMessage(ReportProgressPanel.class, "ReportProgressPanel.statusMessageLabel.text")); // NOI18N
statusMessageLabel.setWrapStyleWord(true);
statusMessageLabel.setBorder(null);
statusMessageLabel.setMaximumSize(new java.awt.Dimension(2147483647, 80));
statusMessageLabel.setMinimumSize(new java.awt.Dimension(101, 80));
statusMessageLabel.setOpaque(false);
statusMessageLabel.setPreferredSize(new java.awt.Dimension(2147483647, 80));
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
@ -389,14 +411,14 @@ public class ReportProgressPanel extends javax.swing.JPanel {
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(statusMessageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(statusMessageLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 474, Short.MAX_VALUE)
.addComponent(reportProgressBar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addComponent(reportLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(separationLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 548, Short.MAX_VALUE)))
.addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
layout.setVerticalGroup(
@ -410,7 +432,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
.addComponent(pathLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(separationLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(statusMessageLabel)
.addComponent(statusMessageLabel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(13, 13, 13))
);
}// </editor-fold>//GEN-END:initComponents
@ -421,7 +443,7 @@ public class ReportProgressPanel extends javax.swing.JPanel {
private javax.swing.JLabel reportLabel;
private javax.swing.JProgressBar reportProgressBar;
private javax.swing.JLabel separationLabel;
private javax.swing.JLabel statusMessageLabel;
private javax.swing.JTextArea statusMessageLabel;
// End of variables declaration//GEN-END:variables
/**

View File

@ -1378,7 +1378,7 @@ public class PortableCaseReportModule implements ReportModule {
}
try {
OsAccountRealm newRealm = newRealmManager.newWindowsRealm(oldRealm.getRealmAddr().orElse(null), realmName, newHost, oldRealm.getScope());
OsAccountRealm newRealm = newRealmManager.newWindowsRealm(oldOsAccount.getAddr().orElse(null), realmName, newHost, oldRealm.getScope());
oldRealmIdToNewRealm.put(oldOsAccount.getRealmId(), newRealm);
} catch (NotUserSIDException ex) {
throw new TskCoreException("Failed to copy OsAccountRealm with ID=" + oldOsAccount.getRealmId(), ex);

View File

@ -1,18 +1,18 @@
body {margin: 0px; padding: 0px; background: #FFFFFF; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353;}
#snapshot{max-width:800; max-height:600}
#content {padding: 30px;}
#header {width:100%; padding: 10px; line-height: 25px; background: #07A; color: #FFF; font-size: 20px;}
h1 {font-size: 20px; font-weight: normal; color: #07A; padding: 0 0 7px 0; margin-top: 25px; border-bottom: 1px solid #D6D6D6;}
h2 {font-size: 20px; font-weight: bolder; color: #07A;}
h3 {font-size: 16px; color: #07A;}
h4 {background: #07A; color: #FFF; font-size: 16px; margin: 0 0 0 25px; padding: 0; padding-left: 15px;}
#header {width:100%; padding: 10px; line-height: 25px; background: #0077AA; color: #FFFFFF; font-size: 20px;}
h1 {font-size: 20px; font-weight: normal; color: #0077AA; padding: 0 0 7px 0; margin-top: 25px; border-bottom: 1px solid #D6D6D6;}
h2 {font-size: 20px; font-weight: bolder; color: #0077AA;}
h3 {font-size: 16px; color: #0077AA;}
h4 {background: #0077AA; color: #FFFFFF; font-size: 16px; margin: 0 0 0 25px; padding: 0; padding-left: 15px;}
ul.nav {list-style-type: none; line-height: 35px; padding: 0px; margin-left: 15px;}
ul li a {font-size: 14px; color: #444; text-decoration: none; padding-left: 25px;}
ul li a {font-size: 14px; color: #444444; text-decoration: none; padding-left: 25px;}
ul li a:hover {text-decoration: underline;}
p {margin: 0 0 20px 0;}
table {white-space:nowrap; min-width: 800px; padding: 2; margin: 0; border-collapse: collapse; border-bottom: 2px solid #e5e5e5;}
.keyword_list table {margin: 0 0 25px 25px; border-bottom: 2px solid #dedede;}
table th {white-space:nowrap; display: table-cell; text-align: center; padding: 2px 4px; background: #e5e5e5; color: #777; font-size: 11px; text-shadow: #e9f9fd 0 1px 0; border-top: 1px solid #dedede; border-bottom: 2px solid #e5e5e5;}
table th {white-space:nowrap; display: table-cell; text-align: center; padding: 2px 4px; background: #e5e5e5; color: #777777; font-size: 11px; text-shadow: #e9f9fd 0 1px 0; border-top: 1px solid #dedede; border-bottom: 2px solid #e5e5e5;}
table .left_align_cell{display: table-cell; padding: 2px 4px; font: 13px/20px Arial, Helvetica, sans-serif; min-width: 125px; overflow: auto; text-align: left; }
table .right_align_cell{display: table-cell; padding: 2px 4px; font: 13px/20px Arial, Helvetica, sans-serif; min-width: 125px; overflow: auto; text-align: right; }
table td {white-space:nowrap; display: table-cell; padding: 2px 3px; font: 13px/20px Arial, Helvetica, sans-serif; min-width: 125px; overflow: auto; text-align:left; }

View File

@ -1,8 +1,8 @@
body { padding: 0px; margin: 0px; font: 13px/20px Arial, Helvetica, sans-serif; color: #535353; }
body { padding: 0px; margin: 0px; font: 13px Arial, Helvetica, sans-serif; color: #535353; }
#wrapper { width: 90%; margin: 0px auto; margin-top: 35px; }
h1 { color: #07A; font-size: 36px; line-height: 42px; font-weight: normal; margin: 0px; border-bottom: 1px solid #81B9DB; }
h1 span { color: #F00; display: block; font-size: 16px; font-weight: bold; line-height: 22px;}
h2 { padding: 0 0 3px 0; margin: 0px; color: #07A; font-weight: normal; border-bottom: 1px dotted #81B9DB; }
h1 { color: #0077AA; font-size: 36px; line-height: 42px; font-weight: normal; margin: 0px; border-bottom: 1px solid #81B9DB; }
h1 span { color: #FF0000; display: block; font-size: 16px; font-weight: bold; line-height: 22px;}
h2 { padding: 0 0 3px 0; margin: 0px; color: #0077AA; font-weight: normal; border-bottom: 1px dotted #81B9DB; }
table td { padding-right: 25px; }
p.subheadding { padding: 0px; margin: 0px; font-size: 11px; color: #B5B5B5; }
.title { width: 660px; margin-bottom: 50px; }
@ -10,5 +10,5 @@ p.subheadding { padding: 0px; margin: 0px; font-size: 11px; color: #B5B5B5; }
.left img { max-width: 250px; max-height: 250px; min-width: 200px; min-height: 200px; }
.right { float: right; width: 385px; margin-top: 25px; font-size: 14px; }
.clear { clear: both; }
.info p { padding: 3px 10px; background: #e5e5e5; color: #777; font-size: 12px; font-weight: bold; text-shadow: #e9f9fd 0 1px 0; border-top: 1px solid #dedede; border-bottom: 2px solid #dedede; }
.info p { padding: 3px 10px; background: #e5e5e5; color: #777777; font-size: 12px; font-weight: bold; text-shadow: #e9f9fd 0 1px 0; border-top: 1px solid #dedede; border-bottom: 2px solid #dedede; }
.info table { margin: 0 25px 20px 25px; }

View File

@ -20,7 +20,8 @@ package org.sleuthkit.autopsy.test;
import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.DatatypeConverter;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.joda.time.DateTime;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.datamodel.Blackboard;
@ -95,13 +96,13 @@ final class CustomArtifactType {
* @throws Blackboard.BlackboardException If there is an error posting the
* artifact to the blackboard.
*/
static BlackboardArtifact createAndPostInstance(Content source, long ingestJobId) throws TskCoreException, Blackboard.BlackboardException {
static BlackboardArtifact createAndPostInstance(Content source, long ingestJobId) throws TskCoreException, Blackboard.BlackboardException, DecoderException {
List<BlackboardAttribute> attributes = new ArrayList<>();
attributes.add(new BlackboardAttribute(intAttrType, MODULE_NAME, 0));
attributes.add(new BlackboardAttribute(doubleAttrType, MODULE_NAME, 0.0));
attributes.add(new BlackboardAttribute(longAttributeType, MODULE_NAME, 0L));
attributes.add(new BlackboardAttribute(dateTimeAttrType, MODULE_NAME, DateTime.now().getMillis()/1000));
attributes.add(new BlackboardAttribute(bytesAttrType, MODULE_NAME, DatatypeConverter.parseHexBinary("ABCD")));
attributes.add(new BlackboardAttribute(dateTimeAttrType, MODULE_NAME, 60L));
attributes.add(new BlackboardAttribute(bytesAttrType, MODULE_NAME, Hex.decodeHex("ABCD")));
attributes.add(new BlackboardAttribute(stringAttrType, MODULE_NAME, "Zero"));
attributes.add(new BlackboardAttribute(jsonAttrType, MODULE_NAME, "{\"fruit\": \"Apple\",\"size\": \"Large\",\"color\": \"Red\"}"));

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.test;
import java.util.logging.Level;
import org.apache.commons.codec.DecoderException;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleAdapter;
@ -73,7 +74,7 @@ public class CustomArtifactsCreatorDataSourceIngestModule extends DataSourceInge
public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
try {
CustomArtifactType.createAndPostInstance(dataSource, context.getJobId());
} catch (TskCoreException | Blackboard.BlackboardException ex) {
} catch (TskCoreException | Blackboard.BlackboardException | DecoderException ex) {
logger.log(Level.SEVERE, String.format("Failed to process data source (obj_id = %d)", dataSource.getId()), ex);
return ProcessResult.ERROR;
}

View File

@ -19,6 +19,7 @@
package org.sleuthkit.autopsy.test;
import java.util.logging.Level;
import org.apache.commons.codec.DecoderException;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.FileIngestModuleAdapter;
@ -74,7 +75,7 @@ final class CustomArtifactsCreatorFileIngestModule extends FileIngestModuleAdapt
}
try {
CustomArtifactType.createAndPostInstance(file, context.getJobId());
} catch (TskCoreException | Blackboard.BlackboardException ex) {
} catch (TskCoreException | Blackboard.BlackboardException | DecoderException ex) {
logger.log(Level.SEVERE, String.format("Failed to process file (obj_id = %d)", file.getId()), ex);
return ProcessResult.ERROR;
}

View File

@ -25,10 +25,11 @@ import javafx.scene.control.TableCell;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TreeTableCell;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
/**
* An abstract base class for Cell factories. This class provides the basic
* infrustructure for implementations to be able to create similar cells for
* infrastructure for implementations to be able to create similar cells for
* ListView, TableViews or TreeTableViews via the appropriate method call.
* Implementations need only implement the abstract configureCell method in the
* same spirit as IndexedCell.updateItem
@ -64,6 +65,12 @@ public abstract class AbstractFXCellFactory<X, Y> {
@Override
protected void updateItem(Y item, boolean empty) {
super.updateItem(item, empty);
// Due to a JavaFX issue in Java 10+,
// https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8231644
// the arrows to expand the tree were removed (FilterTable.css)
// and the following code was added to indent the subnodes.
TreeTableView<X> treeTableView = this.treeTableViewProperty().get();
this.setTranslateX(treeTableView.getTreeItemLevel(treeTableView.getTreeItem(getIndex())) << 4);
configureCell(this, item, empty, (() -> this.getTreeTableRow().getItem()));
}
}

View File

@ -662,6 +662,7 @@ final public class ViewFrame extends BorderPane {
: defaultTimeNavigationNodes);
//do further setup of new view.
ActionUtils.unconfigureButton(refreshButton);
ActionUtils.configureButton(new Refresh(), refreshButton);//configure new refresh action for new view
hostedView.refresh();
notificationPane.setContent(hostedView);

View File

@ -1,6 +1,6 @@
.guide-line{
-fx-opacity: .5;
-fx-stroke: red;
-fx-stroke: #FF0000;
-fx-stroke-dash-array: 5 5;
-fx-stroke-width: 3;
-fx-cursor: h-resize;

View File

@ -24,6 +24,7 @@ import javafx.beans.InvalidationListener;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.Cell;
@ -35,6 +36,7 @@ import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.BorderPane;
import org.controlsfx.control.action.Action;
import org.controlsfx.control.action.ActionUtils;
@ -117,6 +119,8 @@ final public class FilterSetPanel extends BorderPane {
//type is the only filter expanded initialy
expansionMap.put(filteredEvents.getEventFilterState().getFilter(), true);
expansionMap.put(filteredEvents.getEventFilterState().getEventTypeFilterState().getFilter(), true);
expansionMap.put(filteredEvents.getEventFilterState().getDataSourcesFilterState().getFilter(), true);
expansionMap.put(filteredEvents.getEventFilterState().getFileTypesFilterState().getFilter(), true);
InvalidationListener applyFiltersListener = observable -> applyFilters();
@ -128,7 +132,7 @@ final public class FilterSetPanel extends BorderPane {
refreshFilterUI();
hiddenDescriptionsListView.setItems(controller.getQuickHideFilters());
hiddenDescriptionsListView.setCellFactory(listView -> getNewDiscriptionFilterListCell());
hiddenDescriptionsListView.setCellFactory(listView -> getNewDescriptionFilterListCell());
//show and hide the "hidden descriptions" panel depending on the current view mode
controller.viewModeProperty().addListener(observable -> {
@ -154,6 +158,14 @@ final public class FilterSetPanel extends BorderPane {
throw new UnsupportedOperationException("Unknown ViewMode: " + controller.getViewMode());
}
});
//Block the default treetable keyboard events.
filterTreeTable.addEventFilter(KeyEvent.ANY, new EventHandler<KeyEvent>() {
@Override
public void handle(KeyEvent event) {
event.consume();
}
});
}
public FilterSetPanel(TimeLineController controller) {
@ -173,7 +185,7 @@ final public class FilterSetPanel extends BorderPane {
});
}
private ListCell<DescriptionFilterState> getNewDiscriptionFilterListCell() {
private ListCell<DescriptionFilterState> getNewDescriptionFilterListCell() {
final ListCell<DescriptionFilterState> cell = new FilterCheckBoxCellFactory< DescriptionFilterState>().forList();
cell.itemProperty().addListener(itemProperty -> {
if (cell.getItem() == null) {

View File

@ -1,3 +1,16 @@
.column-header-background { visibility: hidden; -fx-padding: -1em; }
.tree-disclosure-node {
-fx-padding: 0px;
-fx-background-color: transparent;
}
.tree-disclosure-node .arrow {
-fx-background-color: -fx-mark-color;
-fx-padding: 0.0em;
}
.tree-table-row-cell {
-fx-table-cell-border-color: transparent;
}

View File

@ -44,8 +44,8 @@ class FilterTreeItem extends TreeItem<FilterState<?>> {
super(filterState);
//keep expanion map upto date if user expands/collapses filter
expandedProperty().addListener(expandedProperty -> expansionMap.put(filterState.getFilter(), isExpanded()));
setExpanded(expansionMap.getOrDefault(filterState.getFilter(), false));
expandedProperty().addListener(expandedProperty -> expansionMap.put(filterState.getFilter(), true));
setExpanded(true);
//if the filter is a compound filter, add its subfilters to the tree
if (filterState instanceof CompoundFilterState<?, ?>) {

View File

@ -14,7 +14,7 @@ import javafx.collections.ObservableList;
import javafx.collections.transformation.TransformationList;
/**
*
* Maps an observable list of type E to an observable list of type F.
*/
public class MappedList<E, F> extends TransformationList<E, F> {
private final Function<F, E> mapper;
@ -112,4 +112,9 @@ public class MappedList<E, F> extends TransformationList<E, F> {
});
}
@Override
public int getViewIndex(int index) {
return index;
}
}

View File

@ -1,13 +1,7 @@
<project name="NativeCoreLibs">
<target name="build-native-libs" description="build native library dependencies">
<!-- sigar: note, matching jar is pulled with ivy -->
<mkdir dir="${lib.dir}"/>
<unzip src="${thirdparty.dir}/sigar/1.6.4/sigar-native.zip" dest="${lib.dir}" >
<!-- get all, rely on jna to locate <patternset>
<include name="**/*.dylib"/>
</patternset> -->
</unzip>
</target>
</project>

View File

@ -1,13 +1,7 @@
<project name="NativeCoreLibs">
<target name="build-native-libs" description="build native library dependencies">
<!-- sigar: note, matching jar is pulled with ivy -->
<mkdir dir="${lib.dir}"/>
<unzip src="${thirdparty.dir}/sigar/1.6.4/sigar-native.zip" dest="${lib.dir}" >
<!-- get all, rely on jna to locate <patternset>
<include name="**/*.so"/>
</patternset> -->
</unzip>
</target>
</project>

View File

@ -1,13 +1,7 @@
<project name="NativeCoreLibs">
<target name="build-native-libs" description="build native library dependencies">
<!-- sigar: note, matching jar is pulled with ivy -->
<mkdir dir="${lib.dir}"/>
<unzip src="${thirdparty.dir}/sigar/1.6.4/sigar-native.zip" dest="${lib.dir}" >
<!-- get all, rely on jna to locate <patternset>
<include name="**/*.dll"/>
</patternset> -->
</unzip>
</target>
</project>

View File

@ -41,24 +41,25 @@
<dependency conf="autopsy_core->default" org="net.htmlparser.jericho" name="jericho-html" rev="3.4"/>
<dependency conf="autopsy_core->default" org="com.fasterxml.jackson.dataformat" name="jackson-dataformat-csv" rev="2.13.2"/>
<!-- process and system monitoring, note: matching native libs pulled from thirdparty -->
<dependency conf="autopsy_core->default" org="org.fusesource" name="sigar" rev="1.6.4" />
<!-- better image resizing -->
<dependency conf="autopsy_core->default" org="org.imgscalr" name="imgscalr-lib" rev="4.2" />
<!-- timeline and image analyzer -->
<!-- ControlsFX after version 9.0.0 has a bug that causes the Image Gallery GridView
to constantly reload images (JIRA-6724). Do not upgrade ControlsFX unless you can
confirm that the following issue is fixed.
https://github.com/controlsfx/controlsfx/issues/1241
-->
<dependency conf="autopsy_core->*" org="org.controlsfx" name="controlsfx" rev="11.1.2" />
<dependency conf="autopsy_core->default" org="joda-time" name="joda-time" rev="2.10.14" />
<!-- timeline -->
<!-- NOTE: the version of these dependencies appears to be tied to javafx / java version -->
<dependency conf="autopsy_core->default" org="org.controlsfx" name="controlsfx" rev="8.40.11" />
<dependency conf="autopsy_core->default" org="org.jfxtras" name="jfxtras-fxml" rev="8.0-r4" />
<dependency conf="autopsy_core->default" org="org.jfxtras" name="jfxtras-controls" rev="8.0-r4" />
<dependency conf="autopsy_core->default" org="org.jfxtras" name="jfxtras-common" rev="8.0-r4" />
<dependency conf="autopsy_core->default" org="org.jfxtras" name="jfxtras-fxml" rev="17-r1" />
<dependency conf="autopsy_core->default" org="org.jfxtras" name="jfxtras-controls" rev="17-r1" />
<dependency conf="autopsy_core->default" org="org.jfxtras" name="jfxtras-common" rev="17-r1" />
<!-- templateing engine used by timeline to generate its snapshot report -->
<dependency conf="autopsy_core->default" org="com.github.spullara.mustache.java" name="compiler" rev="0.9.10" />

View File

@ -26,7 +26,7 @@ file.reference.commons-text-1.9.jar=release/modules/ext/commons-text-1.9.jar
file.reference.commons-validator-1.7.jar=release/modules/ext/commons-validator-1.7.jar
file.reference.compiler-0.9.10.jar=release/modules/ext/compiler-0.9.10.jar
file.reference.conscrypt-openjdk-uber-2.5.1.jar=release/modules/ext/conscrypt-openjdk-uber-2.5.1.jar
file.reference.controlsfx-8.40.11.jar=release/modules/ext/controlsfx-8.40.11.jar
file.reference.controlsfx-11.1.2.jar=release/modules/ext/controlsfx-11.1.2.jar
file.reference.dd-plist-1.23.jar=release/modules/ext/dd-plist-1.23.jar
file.reference.error_prone_annotations-2.11.0.jar=release/modules/ext/error_prone_annotations-2.11.0.jar
file.reference.failureaccess-1.0.1.jar=release/modules/ext/failureaccess-1.0.1.jar
@ -85,9 +85,9 @@ file.reference.jackson-databind-2.13.2.jar=release/modules/ext/jackson-databind-
file.reference.jackson-dataformat-csv-2.13.2.jar=release/modules/ext/jackson-dataformat-csv-2.13.2.jar
file.reference.javax.annotation-api-1.3.2.jar=release/modules/ext/javax.annotation-api-1.3.2.jar
file.reference.jericho-html-3.4.jar=release/modules/ext/jericho-html-3.4.jar
file.reference.jfxtras-common-8.0-r4.jar=release/modules/ext/jfxtras-common-8.0-r4.jar
file.reference.jfxtras-controls-8.0-r4.jar=release/modules/ext/jfxtras-controls-8.0-r4.jar
file.reference.jfxtras-fxml-8.0-r4.jar=release/modules/ext/jfxtras-fxml-8.0-r4.jar
file.reference.jfxtras-common-17-r1.jar=release/modules/ext/jfxtras-common-17-r1.jar
file.reference.jfxtras-controls-17-r1.jar=release/modules/ext/jfxtras-controls-17-r1.jar
file.reference.jfxtras-fxml-17-r1.jar=release/modules/ext/jfxtras-fxml-17-r1.jar
file.reference.jna-5.13.0.jar=release/modules/ext/jna-5.13.0.jar
file.reference.jna-platform-5.13.0.jar=release/modules/ext/jna-platform-5.13.0.jar
file.reference.joda-time-2.10.14.jar=release/modules/ext/joda-time-2.10.14.jar
@ -96,7 +96,6 @@ file.reference.LGoodDatePicker-11.2.1.jar=release/modules/ext/LGoodDatePicker-11
file.reference.listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar=release/modules/ext/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
file.reference.log4j-api-2.17.2.jar=release/modules/ext/log4j-api-2.17.2.jar
file.reference.log4j-core-2.17.2.jar=release/modules/ext/log4j-core-2.17.2.jar
file.reference.ooxml-schemas-1.4.jar=release/modules/ext/ooxml-schemas-1.4.jar
file.reference.opencensus-api-0.31.0.jar=release/modules/ext/opencensus-api-0.31.0.jar
file.reference.opencensus-contrib-http-util-0.31.0.jar=release/modules/ext/opencensus-contrib-http-util-0.31.0.jar
file.reference.opencensus-proto-0.2.0.jar=release/modules/ext/opencensus-proto-0.2.0.jar
@ -110,12 +109,10 @@ file.reference.protobuf-java-3.19.4.jar=release/modules/ext/protobuf-java-3.19.4
file.reference.protobuf-java-util-3.19.4.jar=release/modules/ext/protobuf-java-util-3.19.4.jar
file.reference.re2j-1.5.jar=release/modules/ext/re2j-1.5.jar
file.reference.reload4j-1.2.19.jar=release/modules/ext/reload4j-1.2.19.jar
file.reference.sigar-1.6.4.jar=release/modules/ext/sigar-1.6.4.jar
file.reference.slf4j-api-1.7.36.jar=release/modules/ext/slf4j-api-1.7.36.jar
file.reference.slf4j-reload4j-1.7.36.jar=release/modules/ext/slf4j-reload4j-1.7.36.jar
file.reference.threetenbp-1.5.2.jar=release/modules/ext/threetenbp-1.5.2.jar
file.reference.webp-imageio-sejda-0.1.0.jar=release/modules/ext/webp-imageio-sejda-0.1.0.jar
javac.source=1.8
javac.source=17
javac.compilerargs=-Xlint -Xlint:-serial
nbm.needs.restart=true

View File

@ -11,7 +11,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.25.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -19,7 +19,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.4.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
</module-dependencies>
@ -246,6 +246,19 @@
<package>javax.annotation</package>
<package>javax.annotation.concurrent</package>
<package>javax.annotation.meta</package>
<package>javax.jms</package>
<package>javax.mail</package>
<package>javax.mail.event</package>
<package>javax.mail.internet</package>
<package>javax.mail.search</package>
<package>javax.mail.util</package>
<package>javax.servlet</package>
<package>javax.servlet.http</package>
<package>javax.xml.parsers</package>
<package>javax.xml.transform</package>
<package>javax.xml.transform.dom</package>
<package>javax.xml.transform.sax</package>
<package>javax.xml.transform.stream</package>
<package>jfxtras.animation</package>
<package>jfxtras.css</package>
<package>jfxtras.css.converters</package>
@ -313,6 +326,16 @@
<package>org.apache.commons.lang3.tuple</package>
<package>org.apache.commons.logging</package>
<package>org.apache.commons.logging.impl</package>
<package>org.apache.log</package>
<package>org.apache.log.filter</package>
<package>org.apache.log.format</package>
<package>org.apache.log.output</package>
<package>org.apache.log.output.db</package>
<package>org.apache.log.output.io</package>
<package>org.apache.log.output.io.rotate</package>
<package>org.apache.log.output.jms</package>
<package>org.apache.log.output.net</package>
<package>org.apache.log.util</package>
<package>org.apache.commons.text</package>
<package>org.apache.commons.validator.routines</package>
<package>org.apache.commons.validator.routines.checkdigit</package>
@ -401,7 +424,6 @@
<package>org.controlsfx.control.action</package>
<package>org.controlsfx.control.cell</package>
<package>org.controlsfx.control.decoration</package>
<package>org.controlsfx.control.spreadsheet</package>
<package>org.controlsfx.control.table</package>
<package>org.controlsfx.control.table.model</package>
<package>org.controlsfx.control.textfield</package>
@ -423,17 +445,6 @@
<package>org.freedesktop.gstreamer.message</package>
<package>org.freedesktop.gstreamer.query</package>
<package>org.freedesktop.gstreamer.webrtc</package>
<package>org.hyperic.jni</package>
<package>org.hyperic.sigar</package>
<package>org.hyperic.sigar.cmd</package>
<package>org.hyperic.sigar.jmx</package>
<package>org.hyperic.sigar.pager</package>
<package>org.hyperic.sigar.ptql</package>
<package>org.hyperic.sigar.shell</package>
<package>org.hyperic.sigar.test</package>
<package>org.hyperic.sigar.util</package>
<package>org.hyperic.sigar.vmware</package>
<package>org.hyperic.sigar.win32</package>
<package>org.imgscalr</package>
<package>org.joda.time</package>
<package>org.joda.time.base</package>
@ -460,7 +471,7 @@
<package>org.slf4j.helpers</package>
<package>org.slf4j.spi</package>
</public-packages>
<class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/animal-sniffer-annotations-1.21.jar</runtime-relative-path>
<binary-origin>release/modules/ext/animal-sniffer-annotations-1.21.jar</binary-origin>
</class-path-extension>
@ -573,8 +584,8 @@
<binary-origin>release/modules/ext/conscrypt-openjdk-uber-2.5.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/controlsfx-8.40.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/controlsfx-8.40.11.jar</binary-origin>
<runtime-relative-path>ext/controlsfx-11.1.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/controlsfx-11.1.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/dd-plist-1.23.jar</runtime-relative-path>
@ -809,16 +820,16 @@
<binary-origin>release/modules/ext/jericho-html-3.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jfxtras-common-8.0-r4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-common-8.0-r4.jar</binary-origin>
<runtime-relative-path>ext/jfxtras-common-17-r1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-common-17-r1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jfxtras-controls-8.0-r4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-controls-8.0-r4.jar</binary-origin>
<runtime-relative-path>ext/jfxtras-controls-17-r1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-controls-17-r1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jfxtras-fxml-8.0-r4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-fxml-8.0-r4.jar</binary-origin>
<runtime-relative-path>ext/jfxtras-fxml-17-r1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jfxtras-fxml-17-r1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jna-5.13.0.jar</runtime-relative-path>
@ -852,10 +863,6 @@
<runtime-relative-path>ext/log4j-core-2.17.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/log4j-core-2.17.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/ooxml-schemas-1.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/ooxml-schemas-1.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/opencensus-api-0.31.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/opencensus-api-0.31.0.jar</binary-origin>
@ -908,10 +915,6 @@
<runtime-relative-path>ext/reload4j-1.2.19.jar</runtime-relative-path>
<binary-origin>release/modules/ext/reload4j-1.2.19.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sigar-1.6.4.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sigar-1.6.4.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/slf4j-api-1.7.36.jar</runtime-relative-path>
<binary-origin>release/modules/ext/slf4j-api-1.7.36.jar</binary-origin>

View File

@ -4,4 +4,3 @@ OpenIDE-Module-Long-Description=\
The libraries can also be imported by other modules.
OpenIDE-Module-Name=Autopsy-CoreLibs
OpenIDE-Module-Short-Description=Autopsy Core module external libraries
SigarLoader.linkErr.msg=Could not load sigar library for your environment (non-critical), OS-level metrics will be unavailable.

View File

@ -1,67 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.corelibs;
import com.sun.javafx.PlatformUtil;
import org.hyperic.sigar.Sigar;
import org.openide.util.NbBundle;
/**
* Wrapper over Sigar instrumentation class to facilitate dll loading. Our setup
* bypasses Sigar library loader which does not work well for netbeans
* environment We are responsible for loading the library ourselves.
*/
public class SigarLoader {
private static volatile Sigar sigar;
static {
//bypass the process of validation/loading of the library by sigar jar
System.setProperty("org.hyperic.sigar.path", "-");
//System.setProperty(org.hyperic.sigar.SigarLoader.PROP_SIGAR_JAR_NAME, "sigar-1.6.4.jar");
}
public static Sigar getSigar() {
if (sigar == null) {
synchronized (SigarLoader.class) {
if (sigar == null) {
try {
//rely on netbeans / jna to locate the lib variation for architecture/OS
if (PlatformUtil.isWindows()) {
System.loadLibrary("libsigar"); //NON-NLS
} else {
System.loadLibrary("sigar"); //NON-NLS
}
sigar = new Sigar();
sigar.enableLogging(false); //forces a test
} catch (UnsatisfiedLinkError ex) {
String msg = NbBundle.getMessage(SigarLoader.class, "SigarLoader.linkErr.msg");
System.out.println(msg + ex.toString());
} catch (Exception ex) {
String msg = NbBundle.getMessage(SigarLoader.class, "SigarLoader.linkErr.msg");
System.out.println(msg + ex.toString());
}
}
}
}
return sigar;
}
}

View File

@ -4,10 +4,10 @@
<conf name="coretestlibs"/>
</configurations>
<dependencies >
<dependency conf="coretestlibs->default" org="org.mockito" name="mockito-core" rev="3.5.7"/>
<dependency conf="coretestlibs->default" org="net.bytebuddy" name="byte-buddy" rev="1.10.13"/>
<dependency conf="coretestlibs->default" org="net.bytebuddy" name="byte-buddy-agent" rev="1.10.13"/>
<dependency conf="coretestlibs->default" org="org.objenesis" name="objenesis" rev="3.1"/>
<dependency conf="coretestlibs->default" org="org.mockito" name="mockito-core" rev="4.8.1"/>
<dependency conf="coretestlibs->default" org="net.bytebuddy" name="byte-buddy" rev="1.12.18"/>
<dependency conf="coretestlibs->default" org="net.bytebuddy" name="byte-buddy-agent" rev="1.12.18"/>
<dependency conf="coretestlibs->default" org="org.objenesis" name="objenesis" rev="3.3"/>
<dependency conf="coretestlibs->default" org="junit" name="junit" rev="4.13.2"/>
</dependencies>
</ivy-module>

View File

@ -2,7 +2,7 @@ file.reference.byte-buddy-1.10.13.jar=release/modules/ext/byte-buddy-1.10.13.jar
file.reference.byte-buddy-agent-1.10.13.jar=release/modules/ext/byte-buddy-agent-1.10.13.jar
file.reference.hamcrest-core-1.3.jar=release/modules/ext/hamcrest-core-1.3.jar
file.reference.junit-4.13.2.jar=release/modules/ext/junit-4.13.2.jar
file.reference.mockito-core-3.5.7.jar=release/modules/ext/mockito-core-3.5.7.jar
file.reference.mockito-core-4.8.1.jar=release/modules/ext/mockito-core-4.8.1.jar
file.reference.objenesis-3.1.jar=release/modules/ext/objenesis-3.1.jar
javac.source=1.8
javac.source=11
javac.compilerargs=-Xlint -Xlint:-serial

View File

@ -44,12 +44,12 @@
<package>org.junit.validator</package>
</public-packages>
<class-path-extension>
<runtime-relative-path>ext/byte-buddy-1.10.13.jar</runtime-relative-path>
<binary-origin>release/modules/ext/byte-buddy-1.10.13.jar</binary-origin>
<runtime-relative-path>ext/byte-buddy-1.12.18.jar</runtime-relative-path>
<binary-origin>release/modules/ext/byte-buddy-1.12.18.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/byte-buddy-agent-1.10.13.jar</runtime-relative-path>
<binary-origin>release/modules/ext/byte-buddy-agent-1.10.13.jar</binary-origin>
<runtime-relative-path>ext/byte-buddy-agent-1.12.18.jar</runtime-relative-path>
<binary-origin>release/modules/ext/byte-buddy-agent-1.12.18.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/hamcrest-core-1.3.jar</runtime-relative-path>
@ -60,12 +60,12 @@
<binary-origin>release/modules/ext/junit-4.13.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/mockito-core-3.5.7.jar</runtime-relative-path>
<binary-origin>release/modules/ext/mockito-core-3.5.7.jar</binary-origin>
<runtime-relative-path>ext/mockito-core-4.8.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/mockito-core-4.8.1.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/objenesis-3.1.jar</runtime-relative-path>
<binary-origin>release/modules/ext/objenesis-3.1.jar</binary-origin>
<runtime-relative-path>ext/objenesis-3.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/objenesis-3.3.jar</binary-origin>
</class-path-extension>
</data>
</configuration>

View File

@ -1,4 +1,4 @@
file.reference.jtidy-r938.jar=release/modules/ext/jtidy-r938.jar
javac.source=1.8
javac.source=17
javac.compilerargs=-Xlint -Xlint:-serial
spec.version.base=1.0

View File

@ -12,7 +12,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.47.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -21,7 +21,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.44.1</specification-version>
<specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -30,7 +30,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.49.1</specification-version>
<specification-version>1.66</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -38,7 +38,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.34.1</specification-version>
<specification-version>1.51</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -46,7 +46,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.65.1</specification-version>
<specification-version>7.85</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -54,7 +54,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.41.1</specification-version>
<specification-version>7.63</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -62,7 +62,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.62.1</specification-version>
<specification-version>6.79</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -70,7 +70,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.8.1</specification-version>
<specification-version>9.29</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -78,7 +78,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.63.2</specification-version>
<specification-version>7.87</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -86,7 +86,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.47.1</specification-version>
<specification-version>7.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -94,7 +94,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.45.1</specification-version>
<specification-version>7.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -102,7 +102,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.5.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -110,7 +110,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.32.1</specification-version>
<specification-version>8.51</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -118,7 +118,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.4.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -126,7 +126,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.74.1</specification-version>
<specification-version>6.94</specification-version>
</run-dependency>
</dependency>
<dependency>

View File

@ -80,6 +80,7 @@ import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import javax.swing.DefaultListModel;
import javax.swing.tree.TreeNode;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.codec.binary.Hex;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
@ -1322,10 +1323,10 @@ public final class FileExporterSettingsPanel extends JPanel {
*/
private TreePath findTreePathByRuleAndArtifactClauseName(String ruleName, String clauseName) {
@SuppressWarnings("unchecked")
Enumeration<DefaultMutableTreeNode> enumeration = rootNode.preorderEnumeration();
Enumeration<TreeNode> enumeration = rootNode.preorderEnumeration();
boolean insideRule = false;
while (enumeration.hasMoreElements()) {
DefaultMutableTreeNode node = enumeration.nextElement();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement();
Item item = (Item) node.getUserObject();
if (item.getItemType() == ItemType.RULE) {
insideRule = node.toString().equalsIgnoreCase(ruleName);
@ -1349,9 +1350,9 @@ public final class FileExporterSettingsPanel extends JPanel {
*/
private TreePath findTreePathByRuleName(String ruleName) {
@SuppressWarnings("unchecked")
Enumeration<DefaultMutableTreeNode> enumeration = rootNode.depthFirstEnumeration();
Enumeration<TreeNode> enumeration = rootNode.depthFirstEnumeration();
while (enumeration.hasMoreElements()) {
DefaultMutableTreeNode node = enumeration.nextElement();
DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement();
if (node.toString().equalsIgnoreCase(ruleName)) {
return new TreePath(node.getPath());
}

View File

@ -1,5 +1,5 @@
file.reference.sqlite-jdbc-3.36.0.3.jar=release/modules/ext/sqlite-jdbc-3.36.0.3.jar
javac.source=1.8
file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar
javac.source=17
javac.compilerargs=-Xlint -Xlint:-serial
license.file=LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/

View File

@ -12,7 +12,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.32.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -20,7 +20,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
<specification-version>1.64</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -28,7 +28,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -37,7 +37,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.31.2</specification-version>
<specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -46,7 +46,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.38.2</specification-version>
<specification-version>1.66</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -54,7 +54,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.55.1</specification-version>
<specification-version>7.85</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -62,7 +62,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.28.1</specification-version>
<specification-version>7.63</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -70,7 +70,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.50.3</specification-version>
<specification-version>6.79</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -78,7 +78,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.35.1</specification-version>
<specification-version>7.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -86,7 +86,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.33.2</specification-version>
<specification-version>7.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -94,7 +94,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.29.3</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -102,7 +102,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.19.1</specification-version>
<specification-version>8.51</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -110,7 +110,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.4.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -118,7 +118,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.60.1</specification-version>
<specification-version>6.94</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -142,8 +142,8 @@
</module-dependencies>
<public-packages/>
<class-path-extension>
<runtime-relative-path>ext/sqlite-jdbc-3.36.0.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.36.0.3.jar</binary-origin>
<runtime-relative-path>ext/sqlite-jdbc-3.42.0.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sqlite-jdbc-3.42.0.0.jar</binary-origin>
</class-path-extension>
</data>
</configuration>

View File

@ -240,7 +240,7 @@ public class GroupPane extends BorderPane {
*/
@ThreadConfined(type = ThreadType.JFX)
private final Map<Long, DrawableCell> cellMap = new HashMap<>();
private final InvalidationListener filesSyncListener = (observable) -> {
final String header = getHeaderString();
final List<Long> fileIds = getGroup().getFileIDs();
@ -658,40 +658,46 @@ public class GroupPane extends BorderPane {
}
}
private class DrawableCell extends GridCell<Long> {
private class DrawableCell extends GridCell<Long> implements AutoCloseable {
private final DrawableTile tile = new DrawableTile(GroupPane.this, controller);
/**
* This stores the last non-null file id. So that only new file ids for
* this item are tracked. This prevents an infinite render loop. See
* https://github.com/controlsfx/controlsfx/issues/1241 for more
* information
*/
private Long oldItem = null;
DrawableCell() {
itemProperty().addListener((ObservableValue<? extends Long> observable, Long oldValue, Long newValue) -> {
if (oldValue != null) {
cellMap.remove(oldValue, DrawableCell.this);
tile.setFile(null);
}
if (newValue != null) {
if (cellMap.containsKey(newValue)) {
if (tile != null) {
// Clear out the old value to prevent out-of-date listeners
// from activating.
cellMap.get(newValue).tile.setFile(null);
}
}
cellMap.put(newValue, DrawableCell.this);
}
});
setGraphic(tile);
}
@Override
protected void updateItem(Long item, boolean empty) {
super.updateItem(item, empty);
tile.setFile(item);
if (item != null && oldItem != item) {
tile.setFile(item);
}
if (item != null) {
cellMap.put(item, this);
oldItem = item;
} else if (oldItem != null) {
cellMap.remove(oldItem);
}
}
void resetItem() {
tile.setFile(null);
}
@Override
public void close() throws Exception {
resetItem();
}
}
/**

View File

@ -18,7 +18,8 @@
<dependency conf="solr-war->default" org="org.apache.solr" name="solr" rev="4.10.4" transitive="false" /> <!-- the war file for embedded Solr 4 -->
<dependency conf="solr-libs->default" name="solr-cell" rev="8.11.2" org="org.apache.solr"/>
<!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-core -->
<dependency conf="autopsy->default" org="org.apache.lucene" name="lucene-core" rev="8.11.2"/>
<!-- Autopsy -->
<dependency conf="autopsy->default" org="org.apache.solr" name="solr-solrj" rev="8.11.2"/>
<dependency conf="autopsy->default" org="com.optimaize.languagedetector" name="language-detector" rev="0.6"/>

View File

@ -6,6 +6,7 @@ file.reference.commons-math3-3.6.1.jar=release/modules/ext/commons-math3-3.6.1.j
file.reference.error_prone_annotations-2.11.0.jar=release/modules/ext/error_prone_annotations-2.11.0.jar
file.reference.failureaccess-1.0.1.jar=release/modules/ext/failureaccess-1.0.1.jar
file.reference.guava-31.1-jre.jar=release/modules/ext/guava-31.1-jre.jar
file.reference.hamcrest-core-1.3.jar=release/modules/ext/hamcrest-core-1.3.jar
file.reference.http2-client-9.4.44.v20210927.jar=release/modules/ext/http2-client-9.4.44.v20210927.jar
file.reference.http2-common-9.4.44.v20210927.jar=release/modules/ext/http2-common-9.4.44.v20210927.jar
file.reference.http2-hpack-9.4.44.v20210927.jar=release/modules/ext/http2-hpack-9.4.44.v20210927.jar
@ -24,6 +25,8 @@ file.reference.jetty-http-9.4.44.v20210927.jar=release/modules/ext/jetty-http-9.
file.reference.jetty-io-9.4.44.v20210927.jar=release/modules/ext/jetty-io-9.4.44.v20210927.jar
file.reference.jetty-util-9.4.44.v20210927.jar=release/modules/ext/jetty-util-9.4.44.v20210927.jar
file.reference.jsonic-1.2.11.jar=release/modules/ext/jsonic-1.2.11.jar
file.reference.jsr305-3.0.2.jar=release/modules/ext/jsr305-3.0.2.jar
file.reference.junit-4.13.2.jar=release/modules/ext/junit-4.13.2.jar
file.reference.language-detector-0.6.jar=release/modules/ext/language-detector-0.6.jar
file.reference.listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar=release/modules/ext/listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar
file.reference.logback-classic-1.2.10.jar=release/modules/ext/logback-classic-1.2.10.jar
@ -38,13 +41,15 @@ file.reference.netty-tcnative-classes-2.0.48.Final.jar=release/modules/ext/netty
file.reference.netty-transport-4.1.68.Final.jar=release/modules/ext/netty-transport-4.1.68.Final.jar
file.reference.netty-transport-native-epoll-4.1.68.Final.jar=release/modules/ext/netty-transport-native-epoll-4.1.68.Final.jar
file.reference.netty-transport-native-unix-common-4.1.68.Final.jar=release/modules/ext/netty-transport-native-unix-common-4.1.68.Final.jar
file.reference.slf4j-api-1.7.36.jar=release/modules/ext/slf4j-api-1.7.36.jar
file.reference.snappy-java-1.1.7.6.jar=release/modules/ext/snappy-java-1.1.7.6.jar
file.reference.solr-solrj-8.11.2.jar=release/modules/ext/solr-solrj-8.11.2.jar
file.reference.stax2-api-4.2.1.jar=release/modules/ext/stax2-api-4.2.1.jar
file.reference.woodstox-core-6.2.4.jar=release/modules/ext/woodstox-core-6.2.4.jar
file.reference.zookeeper-3.8.0.jar=release/modules/ext/zookeeper-3.8.0.jar
file.reference.zookeeper-jute-3.8.0.jar=release/modules/ext/zookeeper-jute-3.8.0.jar
javac.source=1.8
file.reference.lucene-core-8.11.2.jar=release/modules/ext/lucene-core-8.11.2.jar
javac.source=17
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/autopsy/

View File

@ -12,7 +12,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.24.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -20,7 +20,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
<specification-version>1.64</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -28,7 +28,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>1.46.1</specification-version>
<specification-version>1.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -37,7 +37,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.26.1</specification-version>
<specification-version>1.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -46,7 +46,7 @@
<compile-dependency/>
<run-dependency>
<release-version>1</release-version>
<specification-version>1.31.1</specification-version>
<specification-version>1.66</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -54,7 +54,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.31.1</specification-version>
<specification-version>7.85</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -62,7 +62,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.50.3</specification-version>
<specification-version>6.79</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -70,7 +70,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.23.1</specification-version>
<specification-version>7.65</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -78,7 +78,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>7.21.1</specification-version>
<specification-version>7.62</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -86,7 +86,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.15.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -94,7 +94,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>8.8.1</specification-version>
<specification-version>8.51</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -102,7 +102,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>9.4.1</specification-version>
<specification-version>9.25</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -110,7 +110,7 @@
<build-prerequisite/>
<compile-dependency/>
<run-dependency>
<specification-version>6.40.1</specification-version>
<specification-version>6.94</specification-version>
</run-dependency>
</dependency>
<dependency>
@ -266,6 +266,10 @@
<runtime-relative-path>ext/guava-31.1-jre.jar</runtime-relative-path>
<binary-origin>release/modules/ext/guava-31.1-jre.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/hamcrest-core-1.3.jar</runtime-relative-path>
<binary-origin>release/modules/ext/hamcrest-core-1.3.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/http2-client-9.4.44.v20210927.jar</runtime-relative-path>
<binary-origin>release/modules/ext/http2-client-9.4.44.v20210927.jar</binary-origin>
@ -338,6 +342,14 @@
<runtime-relative-path>ext/jsonic-1.2.11.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jsonic-1.2.11.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/jsr305-3.0.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/jsr305-3.0.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/junit-4.13.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/junit-4.13.2.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/language-detector-0.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/language-detector-0.6.jar</binary-origin>
@ -394,6 +406,10 @@
<runtime-relative-path>ext/netty-transport-native-unix-common-4.1.68.Final.jar</runtime-relative-path>
<binary-origin>release/modules/ext/netty-transport-native-unix-common-4.1.68.Final.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/slf4j-api-1.7.36.jar</runtime-relative-path>
<binary-origin>release/modules/ext/slf4j-api-1.7.36.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/snappy-java-1.1.7.6.jar</runtime-relative-path>
<binary-origin>release/modules/ext/snappy-java-1.1.7.6.jar</binary-origin>
@ -418,6 +434,10 @@
<runtime-relative-path>ext/zookeeper-jute-3.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/zookeeper-jute-3.8.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/lucene-core-8.11.2.jar</runtime-relative-path>
<binary-origin>release/modules/ext/lucene-core-8.11.2.jar</binary-origin>
</class-path-extension>
</data>
</configuration>
</project>

View File

@ -1,4 +1,4 @@
@REM set JAVA_HOME=C:\Program Files\ojdkbuild\java-1.8.0-openjdk-1.8.0.222-1
@REM set JAVA_HOME=C:\Program Files\BellSoft\LibericaJDK-17-Full
@REM set SOLR_SERVER_DIR=C:\Bitnami\solr-8.2.0-2/apache-solr/server
set SOLR_PORT=8983
set STOP_PORT=8079

View File

@ -301,7 +301,7 @@
<autoCommit>
<maxTime>300000</maxTime>
<!-- maxDocs>15000</maxDocs -->
<openSearcher>true</openSearcher>
<openSearcher>false</openSearcher>
</autoCommit>
<!-- softAutoCommit is like autoCommit except it causes a

View File

@ -112,9 +112,9 @@ abstract class AdHocSearchPanel extends javax.swing.JPanel {
}
if (filesIndexed == 0) {
if (isIngestRunning) {
// ELTODO this message should be dependent on whether Solr indexing is enabled or not
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.noFilesInIdxMsg",
KeywordSearchSettings.getUpdateFrequency().getTime()), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
"AbstractKeywordSearchPerformer.search.noFilesInIdxMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);
} else {
KeywordSearchUtil.displayDialog(keywordSearchErrorDialogHeader, NbBundle.getMessage(this.getClass(),
"AbstractKeywordSearchPerformer.search.noFilesIdxdMsg"), KeywordSearchUtil.DIALOG_MESSAGE_TYPE.ERROR);

View File

@ -39,8 +39,8 @@ AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=Invalid query statemen
AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle=Keyword Search Ingest in Progress
AbstractKeywordSearchPerformer.search.ingestInProgressBody=<html>Keyword Search Ingest is currently running.<br />Not all files have been indexed and this search might yield incomplete results.<br />Do you want to proceed with this search anyway?</html>
AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody=Keyword list is empty, please add at least one keyword to the list
AbstractKeywordSearchPerformer.search.noFilesInIdxMsg=<html>No files are in index yet. <br />Try again later. Index is updated every {0} minutes.</html>
AbstractKeywordSearchPerformer.search.noFilesIdxdMsg=<html>No files were indexed.<br />Re-ingest the image with the Keyword Search Module enabled. </html>
AbstractKeywordSearchPerformer.search.noFilesInIdxMsg=<html>No files are in index yet. <br />If Solr keyword search indexing was enabled, wait for ingest to complete</html>
AbstractKeywordSearchPerformer.search.noFilesIdxdMsg=<html>No files were indexed.<br />Re-ingest the image with the Keyword Search Module and Solr indexing enabled. </html>
ExtractedContentViewer.toolTip=Displays extracted text from files and keyword-search results. Requires Keyword Search ingest to be run on a file to activate this viewer.
ExtractedContentViewer.getTitle=Indexed Text
HighlightedMatchesSource.toString=Search Results
@ -122,7 +122,7 @@ KeywordSearchListsManagementPanel.fileExtensionFilterLbl=Autopsy Keyword List Fi
KeywordSearchListsManagementPanel.fileExtensionFilterLb2=Encase Keyword List File (txt)
KeywordSearch.listImportFeatureTitle=Keyword List Import
KeywordSearchIngestModule.moduleName=Keyword Search
KeywordSearchIngestModule.moduleDescription=Performs file indexing and periodic search using keywords and regular expressions in lists.
KeywordSearchIngestModule.moduleDescription=Performs file indexing and search using selected keyword lists.
DropdownSearchPanel.keywordTextField.text=
KeywordSearchPanel.searchDropButton.text=Keyword Search
DropdownSearchPanel.exactRadioButton.text=Exact Match
@ -211,11 +211,6 @@ KeywordSearchGlobalLanguageSettingsPanel.enableUTF8Checkbox.text=Enable UTF8 tex
KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest settings for string extraction from unknown file types (changes effective on next ingest):
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction
KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages):
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText=10 minutes (faster overall ingest time than default)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes (slower feedback, faster ingest)
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest:
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText=Requires Hash Set service to had run previously, or be selected for next ingest.
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=Do not add files in NSRL (known files) to keyword index during ingest
KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=Information
@ -224,11 +219,7 @@ KeywordSearchGlobalSearchSettingsPanel.filesIndexedValue.text=0
KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=Files in keyword index:
KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=Show Keyword Preview in Keyword Search Results (will result in longer search times)
KeywordSearchGlobalSearchSettingsPanel.chunksValLabel.text=0
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText=1 minute (overall ingest time will be longest)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute (faster feedback, longest ingest)
KeywordSearchGlobalSearchSettingsPanel.chunksLabel.text=Chunks in keyword index:
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText=5 minutes (overall ingest time will be longer)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text=5 minutes (default)
KeywordSearchIngestModule.regExpHitLbl=Reg Ex hit:
KeywordSearchIngestModule.kwHitLbl=Keyword hit:
KeywordSearchIngestModule.kwHitThLbl=Keyword
@ -254,8 +245,6 @@ KeywordSearchListsManagementPanel.newKeywordListDescription2=Keyword list <{0}>
KeywordSearchModuleFactory.getIngestJobSettingsPanel.exception.msg=Expected settings argument to be instanceof KeywordSearchJobSettings
KeywordSearchModuleFactory.createFileIngestModule.exception.msg=Expected settings argument to be instanceof KeywordSearchJobSettings
SearchRunner.Searcher.done.err.msg=Error performing keyword search
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.toolTipText=Fastest overall, but no results until the end
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.text=No periodic searches
SolrConnectionCheck.HostnameOrPort=Invalid hostname and/or port number.
SolrConnectionCheck.Hostname=Invalid hostname.
SolrConnectionCheck.MissingHostname=Missing hostname.
@ -322,3 +311,4 @@ ExtractedContentPanel.pagesLabel.text=Page:
KeywordSearchJobSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR)
KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text=<html>Only process PDFs, MS Office docs and images which are over 100KB in size or extracted from another file (Beta)</html>
KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text=Only index text extracted using OCR
KeywordSearchJobSettingsPanel.solrCheckbox.text=Add text to Solr Index

View File

@ -15,16 +15,13 @@ ExtractAllTermsReport.error.noOpenCase=No currently open case.
ExtractAllTermsReport.export.error=Error During Unique Word Extraction
ExtractAllTermsReport.exportComplete=Unique Word Extraction Complete
ExtractAllTermsReport.getName.text=Extract Unique Words
# {0} - Number of extracted terms
ExtractAllTermsReport.numberExtractedTerms=Extracted {0} terms...
ExtractAllTermsReport.search.ingestInProgressBody=<html>Keyword Search Ingest is currently running.<br />Not all files have been indexed and unique word extraction might yield incomplete results.<br />Do you want to proceed with unique word extraction anyway?</html>
# {0} - Keyword search commit frequency
ExtractAllTermsReport.search.noFilesInIdxMsg=No files are in index yet. Try again later. Index is updated every {0} minutes.
ExtractAllTermsReport.search.noFilesInIdxMsg2=No files are in index yet. Try again later
ExtractAllTermsReport.search.noFilesInIdxMsg=No files are in index yet. If Solr keyword search indexing and Solr indexing were enabled, wait for ingest to complete.
ExtractAllTermsReport.search.noFilesInIdxMsg2=No files are in index yet. Re-ingest the image with the Keyword Search Module and Solr indexing enabled.
ExtractAllTermsReport.search.searchIngestInProgressTitle=Keyword Search Ingest in Progress
ExtractAllTermsReport.startExport=Starting Unique Word Extraction
ExtractedContentPanel.setMarkup.panelTxt=<span style='font-style:italic'>Loading text... Please wait</span>
# {0} - Content name
ExtractedContentPanel.SetMarkup.progress.loading=Loading text for {0}
GlobalEditListPanel.editKeyword.title=Edit Keyword
GlobalEditListPanel.warning.text=Boundary characters ^ and $ do not match word boundaries. Consider\nreplacing with an explicit list of boundary characters, such as [ \\.,]
@ -91,8 +88,8 @@ AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=Invalid query statemen
AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle=Keyword Search Ingest in Progress
AbstractKeywordSearchPerformer.search.ingestInProgressBody=<html>Keyword Search Ingest is currently running.<br />Not all files have been indexed and this search might yield incomplete results.<br />Do you want to proceed with this search anyway?</html>
AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody=Keyword list is empty, please add at least one keyword to the list
AbstractKeywordSearchPerformer.search.noFilesInIdxMsg=<html>No files are in index yet. <br />Try again later. Index is updated every {0} minutes.</html>
AbstractKeywordSearchPerformer.search.noFilesIdxdMsg=<html>No files were indexed.<br />Re-ingest the image with the Keyword Search Module enabled. </html>
AbstractKeywordSearchPerformer.search.noFilesInIdxMsg=<html>No files are in index yet. <br />If Solr keyword search indexing was enabled, wait for ingest to complete</html>
AbstractKeywordSearchPerformer.search.noFilesIdxdMsg=<html>No files were indexed.<br />Re-ingest the image with the Keyword Search Module and Solr indexing enabled. </html>
ExtractedContentViewer.toolTip=Displays extracted text from files and keyword-search results. Requires Keyword Search ingest to be run on a file to activate this viewer.
ExtractedContentViewer.getTitle=Indexed Text
HighlightedMatchesSource.toString=Search Results
@ -176,7 +173,7 @@ KeywordSearchListsManagementPanel.fileExtensionFilterLbl=Autopsy Keyword List Fi
KeywordSearchListsManagementPanel.fileExtensionFilterLb2=Encase Keyword List File (txt)
KeywordSearch.listImportFeatureTitle=Keyword List Import
KeywordSearchIngestModule.moduleName=Keyword Search
KeywordSearchIngestModule.moduleDescription=Performs file indexing and periodic search using keywords and regular expressions in lists.
KeywordSearchIngestModule.moduleDescription=Performs file indexing and search using selected keyword lists.
DropdownSearchPanel.keywordTextField.text=
KeywordSearchPanel.searchDropButton.text=Keyword Search
DropdownSearchPanel.exactRadioButton.text=Exact Match
@ -227,8 +224,6 @@ KeywordSearchSettings.properties_options.text={0}_Options
KeywordSearchSettings.propertiesNSRL.text={0}_NSRL
KeywordSearchSettings.propertiesScripts.text={0}_Scripts
NoOpenCoreException.err.noOpenSorlCore.msg=No currently open Solr core.
SearchRunner.query.exception.msg=Error performing query:
# {0} - colelction name
Server.deleteCore.exception.msg=Failed to delete Solr colelction {0}
Server.exceptionMessage.unableToBackupCollection=Unable to backup Solr collection
Server.exceptionMessage.unableToCreateCollection=Unable to create Solr collection
@ -272,11 +267,6 @@ KeywordSearchGlobalLanguageSettingsPanel.enableUTF8Checkbox.text=Enable UTF8 tex
KeywordSearchGlobalLanguageSettingsPanel.ingestSettingsLabel.text=Ingest settings for string extraction from unknown file types (changes effective on next ingest):
KeywordSearchGlobalLanguageSettingsPanel.enableUTF16Checkbox.text=Enable UTF16LE and UTF16BE string extraction
KeywordSearchGlobalLanguageSettingsPanel.languagesLabel.text=Enabled scripts (languages):
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20 mins. (fastest ingest time)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20 minutes (slowest feedback, fastest ingest)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText=10 minutes (faster overall ingest time than default)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10 minutes (slower feedback, faster ingest)
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=Results update frequency during ingest:
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText=Requires Hash Set service to had run previously, or be selected for next ingest.
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=Do not add files in NSRL (known files) to keyword index during ingest
KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=Information
@ -285,11 +275,7 @@ KeywordSearchGlobalSearchSettingsPanel.filesIndexedValue.text=0
KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=Files in keyword index:
KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=Show Keyword Preview in Keyword Search Results (will result in longer search times)
KeywordSearchGlobalSearchSettingsPanel.chunksValLabel.text=0
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText=1 minute (overall ingest time will be longest)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1 minute (faster feedback, longest ingest)
KeywordSearchGlobalSearchSettingsPanel.chunksLabel.text=Chunks in keyword index:
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText=5 minutes (overall ingest time will be longer)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text=5 minutes (default)
KeywordSearchIngestModule.regExpHitLbl=Reg Ex hit:
KeywordSearchIngestModule.kwHitLbl=Keyword hit:
KeywordSearchIngestModule.kwHitThLbl=Keyword
@ -315,8 +301,6 @@ KeywordSearchListsManagementPanel.newKeywordListDescription2=Keyword list <{0}>
KeywordSearchModuleFactory.getIngestJobSettingsPanel.exception.msg=Expected settings argument to be instanceof KeywordSearchJobSettings
KeywordSearchModuleFactory.createFileIngestModule.exception.msg=Expected settings argument to be instanceof KeywordSearchJobSettings
SearchRunner.Searcher.done.err.msg=Error performing keyword search
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.toolTipText=Fastest overall, but no results until the end
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.text=No periodic searches
Server.status.failed.msg=Local Solr server did not respond to status request. This may be because the server failed to start or is taking too long to initialize.
SolrConnectionCheck.HostnameOrPort=Invalid hostname and/or port number.
SolrConnectionCheck.Hostname=Invalid hostname.
@ -404,6 +388,7 @@ ExtractedContentPanel.pagesLabel.text=Page:
KeywordSearchJobSettingsPanel.ocrCheckBox.text=Enable Optical Character Recognition (OCR)
KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text=<html>Only process PDFs, MS Office docs and images which are over 100KB in size or extracted from another file (Beta)</html>
KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text=Only index text extracted using OCR
KeywordSearchJobSettingsPanel.solrCheckbox.text=Add text to Solr Index
TextZoomPanel.zoomInButton.text=
TextZoomPanel.zoomOutButton.text=
TextZoomPanel.zoomResetButton.text=Reset

View File

@ -7,8 +7,6 @@ AbstractKeywordSearchPerformer.search.dialogErrorHeader=\u30ad\u30fc\u30ef\u30fc
AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody=\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u304c\u7a7a(\u672a\u5165\u529b)\u3067\u3059\u3002\u5c11\u306a\u304f\u3068\u30821\u3064\u306e\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u30ea\u30b9\u30c8\u306b\u8ffd\u52a0\u3057\u3066\u304f\u3060\u3055\u3044\u3002
AbstractKeywordSearchPerformer.search.ingestInProgressBody=<html>\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u73fe\u5728\u5b9f\u884c\u4e2d\u3067\u3059\u3002<br />\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3055\u308c\u306a\u304b\u3063\u305f\u305f\u3081\u3001\u3053\u306e\u691c\u7d22\u306f\u4e0d\u5b8c\u5168\u306a\u7d50\u679c\u3092\u751f\u6210\u3059\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002<br />\u305d\u308c\u3067\u3082\u3053\u306e\u691c\u7d22\u3092\u7d9a\u884c\u3057\u307e\u3059\u304b?</html>
AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=\u7121\u52b9\u306a\u30af\u30a8\u30ea\u30fb\u30b9\u30c6\u30fc\u30c8\u30e1\u30f3\u30c8\u3002 \u5185\u5bb9\u304c\u6b63\u898f\u8868\u73fe\u306e\u5834\u5408\u3001Lucene\u6b63\u898f\u8868\u73fe\u30d1\u30bf\u30fc\u30f3\u306e\u307f\u304c\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u307e\u3059\u3002 POSIX\u6587\u5b57\u30af\u30e9\u30b9\uff08\\ n\u3084\\ w\u306a\u3069\uff09\u306f\u7121\u52b9\u3067\u3059\u3002
AbstractKeywordSearchPerformer.search.noFilesIdxdMsg=<html>\u30d5\u30a1\u30a4\u30eb\u304c\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3055\u308c\u3066\u3044\u307e\u305b\u3093\u3002<br />\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30e2\u30b8\u30e5\u30fc\u30eb\u3092\u6709\u52b9\u306b\u3057\u305f\u72b6\u614b\u3067\u30a4\u30e1\u30fc\u30b8\u3092\u518d\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u3057\u3066\u304f\u3060\u3055\u3044\u3002</html>
AbstractKeywordSearchPerformer.search.noFilesInIdxMsg=<html>\u307e\u3060\u30d5\u30a1\u30a4\u30eb\u304c\u7d22\u5f15\u306b\u542b\u307e\u308c\u3066\u3044\u307e\u305b\u3093\u3002<br />\u5f8c\u3067\u3082\u3046\u4e00\u5ea6\u304a\u8a66\u3057\u304f\u3060\u3055\u3044\u3002 \u7d22\u5f15\u306f {0} \u5206\u3054\u3068\u306b\u66f4\u65b0\u3055\u308c\u307e\u3059\u3002</html>
AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059
AccountsText.creditCardNumber=\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7
AccountsText.creditCardNumbers=\u30af\u30ec\u30b8\u30c3\u30c8\u30ab\u30fc\u30c9\u756a\u53f7
@ -55,8 +53,6 @@ ExtractAllTermsReport.exportComplete=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\
ExtractAllTermsReport.getName.text=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u3092\u62bd\u51fa\u3059\u308b
ExtractAllTermsReport.numberExtractedTerms=\u62bd\u51fa\u3055\u308c\u305f{0}\u7528\u8a9e...
ExtractAllTermsReport.search.ingestInProgressBody=<html> \u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u8aad\u8fbc\u306f\u73fe\u5728\u5b9f\u884c\u4e2d\u3067\u3059\u3002<br/>\u3059\u3079\u3066\u306e\u30d5\u30a1\u30a4\u30eb\u304c\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u308f\u3051\u3067\u306f\u306a\u304f\u3001\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u3092\u62bd\u51fa\u306f\u4e0d\u5b8c\u5168\u306a\u7d50\u679c\u306b\u306a\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002<br />\u305d\u308c\u3067\u3082\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u306e\u62bd\u51fa\u3092\u7d9a\u884c\u3057\u307e\u3059\u304b\uff1f</ html>
ExtractAllTermsReport.search.noFilesInIdxMsg=\u307e\u3060\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u3042\u3068\u3067\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002 \u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306f{0}\u5206\u3054\u3068\u306b\u66f4\u65b0\u3055\u308c\u307e\u3059\u3002
ExtractAllTermsReport.search.noFilesInIdxMsg2=\u307e\u3060\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u308b\u30d5\u30a1\u30a4\u30eb\u306f\u3042\u308a\u307e\u305b\u3093\u3002 \u3042\u3068\u3067\u3082\u3046\u4e00\u5ea6\u8a66\u3057\u3066\u307f\u3066\u304f\u3060\u3055\u3044\u3002
ExtractAllTermsReport.search.searchIngestInProgressTitle=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059
ExtractAllTermsReport.startExport=\u30e6\u30cb\u30fc\u30af\u306a\u5358\u8a9e\u62bd\u51fa\u306e\u958b\u59cb
ExtractedContentPanel.SetMarkup.progress.loading={0} \u306e\u30c6\u30ad\u30b9\u30c8\u3092\u8aad\u307f\u8fbc\u3093\u3067\u3044\u307e\u3059
@ -210,23 +206,12 @@ KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsLimitedOCR=\u3
KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsOCR=OCR\u6587\u5b57\u8a8d\u8b58\u3092\u6709\u52b9\u306b\u3059\u308b\uff08Windows 64\u30d3\u30c3\u30c8\u304c\u5fc5\u8981\uff09
KeywordSearchGlobalSearchSettingsPanel.filesIndexedLabel.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u7d22\u5f15\u5185\u306e\u30d5\u30a1\u30a4\u30eb\:
KeywordSearchGlobalSearchSettingsPanel.filesIndexedValue.text=0
KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306e\u7d50\u679c\u66f4\u65b0\u983b\u5ea6\:
KeywordSearchGlobalSearchSettingsPanel.informationLabel.text=\u60c5\u5831
KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u9032\u884c\u4e2d\u3067\u3059\u3002\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u304c\u5b8c\u4e86\u3059\u308b\u307e\u3067\u4e00\u90e8\u306e\u8a2d\u5b9a\u3092\u5229\u7528\u3067\u304d\u307e\u305b\u3093\u3002
KeywordSearchGlobalSearchSettingsPanel.settingsLabel.text=\u8a2d\u5b9a
KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text=\u30ad\u30fc\u30ef\u30fc\u30c9\u691c\u7d22\u7d50\u679c\u306b\u30ad\u30fc\u30ef\u30fc\u30c9\u30d7\u30ec\u30d3\u30e5\u30fc\u3092\u8868\u793a(\u691c\u7d22\u6642\u9593\u304c\u9577\u304f\u306a\u308a\u307e\u3059)
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306bNSRL(\u65e2\u77e5\u306e\u30d5\u30a1\u30a4\u30eb)\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u30ad\u30fc\u30ef\u30fc\u30c9\u306b\u8ffd\u52a0\u3057\u306a\u3044\u3067\u304f\u3060\u3055\u3044
KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.toolTipText=\u30cf\u30c3\u30b7\u30e5\u30bb\u30c3\u30c8\u30b5\u30fc\u30d3\u30b9\u306b\u4ee5\u524d\u306b\u5b9f\u884c\u6e08\u307f\u3067\u3042\u308b\u3053\u3068\u3001\u307e\u305f\u306f\u6b21\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u306b\u9078\u629e\u3055\u308c\u308b\u3053\u3068\u3092\u8981\u6c42\u3057\u307e\u3059\u3002
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text=20\u5206(\u6700\u9045\u30d5\u30a3\u30fc\u30c9\u30d0\u30c3\u30af\u3001\u6700\u901f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText=20\u5206(\u6700\u901f\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u6642\u9593)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text=10\u5206(\u3088\u308a\u9045\u3044\u30d5\u30a3\u30fc\u30c9\u30d0\u30c3\u30af\u3001\u3088\u308a\u901f\u3044\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText=10\u5206(\u30c7\u30d5\u30a9\u30eb\u30c8\u3088\u308a\u3082\u901f\u3044\u7dcf\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u6642\u9593)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text=5\u5206(\u30c7\u30d5\u30a9\u30eb\u30c8)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText=5\u5206(\u7dcf\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u6642\u9593\u304c\u9577\u304f\u306a\u308a\u307e\u3059)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1=1\u5206(\u3088\u308a\u901f\u3044\u30d5\u30a3\u30fc\u30c9\u30d0\u30c3\u30af\u3001\u6700\u9577\u306e\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText=1\u5206(\u7dcf\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u6642\u9593\u306f\u6700\u9577\u306b\u306a\u308a\u307e\u3059)
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.text=\u5b9a\u671f\u691c\u7d22\u306a\u3057
KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.toolTipText=\u5168\u4f53\u3067\u6700\u901f\u3067\u3059\u304c\u3001\u6700\u5f8c\u307e\u3067\u7d50\u679c\u306f\u8868\u793a\u3055\u308c\u307e\u305b\u3093
KeywordSearchGlobalSettingsPanel.Title=\u30ad\u30fc\u30ef\u30fc\u30c9\u4e00\u62ec\u691c\u7d22\u8a2d\u5b9a
KeywordSearchIngestModule.doInBackGround.displayName=\u30ad\u30fc\u30ef\u30fc\u30c9\u5b9a\u671f\u691c\u7d22
KeywordSearchIngestModule.doInBackGround.finalizeMsg=\u78ba\u5b9a
@ -271,7 +256,6 @@ KeywordSearchJobSettingsPanel.languagesValLabel.toolTipText=
KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text=<html>\u51e6\u7406\u3092\u3059\u308bPDF\u3001MS Office\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u3001\u3068\u753b\u50cf\u306f100KB\u4ee5\u4e0a\u304b\u307e\u305f\u306f\u30d5\u30a1\u30a4\u30eb\u304b\u3089\u62bd\u51fa\u3057\u305f\u3082\u306e\uff08\u30d9\u30fc\u30bf\u6a5f\u80fd\uff09\u306b\u5236\u9650\u3057\u307e\u3059\u3002</ html>
KeywordSearchJobSettingsPanel.ocrCheckBox.text=OCR\u3092\u6709\u52b9\u306b\u3059\u308b
KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text=OCR\u3092\u4f7f\u7528\u3057\u3066\u62bd\u51fa\u3055\u308c\u305f\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u30fb\u30c6\u30ad\u30b9\u30c8\u306e\u307f
KeywordSearchJobSettingsPanel.titleLabel.text=\u30a4\u30f3\u30b8\u30a7\u30b9\u30c8\u4e2d\u306b\u6709\u52b9\u5316\u3059\u308b\u30ad\u30fc\u30ef\u30fc\u30c9\u30ea\u30b9\u30c8\u3092\u9078\u629e\:
KeywordSearchListsAbstract.addList.errMsg1.msg=KeywordSearchListsAbstract\u66f4\u65b0\u306e\u30ea\u30c3\u30b9\u30f3\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u307e\u3057\u305f\u3002\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5224\u65ad\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
KeywordSearchListsAbstract.addList.errMsg2.msg=KeywordSearchListsAbstract\u66f4\u65b0\u306e\u30ea\u30c3\u30b9\u30f3\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u307e\u3057\u305f\u3002\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5224\u65ad\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002
KeywordSearchListsAbstract.deleteList.errMsg1.msg=KeywordSearchListsAbstract\u66f4\u65b0\u306e\u30ea\u30c3\u30b9\u30f3\u4e2d\u306b\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u30a8\u30e9\u30fc\u3092\u767a\u751f\u3055\u305b\u307e\u3057\u305f\u3002\u30ed\u30b0\u3092\u78ba\u8a8d\u3057\u3066\u3069\u306e\u30e2\u30b8\u30e5\u30fc\u30eb\u304c\u5224\u65ad\u3057\u3066\u304f\u3060\u3055\u3044\u3002\u4e00\u90e8\u306e\u30c7\u30fc\u30bf\u304c\u4e0d\u5b8c\u5168\u3067\u3042\u308b\u53ef\u80fd\u6027\u304c\u3042\u308a\u307e\u3059\u3002

View File

@ -398,6 +398,8 @@ class Chunker implements Iterator<Chunk>, Iterable<Chunk> {
private final StringBuilder sb;
private final int baseChunkSizeChars;
private final StringBuilder lowerCasedChunk;
private boolean hasHit = false;
private int chunkId = 0;
Chunk(StringBuilder sb, int baseChunkSizeChars, StringBuilder lowerCasedChunk) {
this.sb = sb;
@ -420,7 +422,7 @@ class Chunker implements Iterator<Chunk>, Iterable<Chunk> {
*
* @return The content of the chunk.
*/
public String geLowerCasedChunk() {
public String getLowerCasedChunk() {
return lowerCasedChunk.toString();
}
@ -432,5 +434,21 @@ class Chunker implements Iterator<Chunk>, Iterable<Chunk> {
int getBaseChunkLength() {
return baseChunkSizeChars;
}
boolean hasHit() {
return hasHit;
}
void setHasHit(boolean b) {
hasHit = b;
}
void setChunkId(int id) {
chunkId = id;
}
int getChunkId() {
return chunkId;
}
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2018 Basis Technology Corp.
* Copyright 2011-2022 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,7 +30,6 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import javax.swing.JCheckBox;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
@ -143,10 +142,7 @@ class DropdownListSearchPanel extends AdHocSearchPanel {
searchAddListener = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (ingestRunning) {
IngestSearchRunner.getInstance().addKeywordListsToAllJobs(listsTableModel.getSelectedLists());
logger.log(Level.INFO, "Submitted enqueued lists to ingest"); //NON-NLS
} else {
if (!ingestRunning) {
searchAction(e);
}
}

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2021 Basis Technology Corp.
* Copyright 2022 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -51,9 +51,8 @@ public class ExtractAllTermsReport implements GeneralReportModule {
@NbBundle.Messages({
"ExtractAllTermsReport.error.noOpenCase=No currently open case.",
"# {0} - Keyword search commit frequency",
"ExtractAllTermsReport.search.noFilesInIdxMsg=No files are in index yet. Try again later. Index is updated every {0} minutes.",
"ExtractAllTermsReport.search.noFilesInIdxMsg2=No files are in index yet. Try again later",
"ExtractAllTermsReport.search.noFilesInIdxMsg=No files are in index yet. If Solr keyword search indexing and Solr indexing were enabled, wait for ingest to complete.",
"ExtractAllTermsReport.search.noFilesInIdxMsg2=No files are in index yet. Re-ingest the image with the Keyword Search Module and Solr indexing enabled.",
"ExtractAllTermsReport.search.searchIngestInProgressTitle=Keyword Search Ingest in Progress",
"ExtractAllTermsReport.search.ingestInProgressBody=<html>Keyword Search Ingest is currently running.<br />Not all files have been indexed and unique word extraction might yield incomplete results.<br />Do you want to proceed with unique word extraction anyway?</html>",
"ExtractAllTermsReport.startExport=Starting Unique Word Extraction",
@ -83,7 +82,7 @@ public class ExtractAllTermsReport implements GeneralReportModule {
if (filesIndexed == 0) {
if (isIngestRunning) {
progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, Bundle.ExtractAllTermsReport_search_noFilesInIdxMsg(KeywordSearchSettings.getUpdateFrequency().getTime()));
progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, Bundle.ExtractAllTermsReport_search_noFilesInIdxMsg());
} else {
progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR, Bundle.ExtractAllTermsReport_search_noFilesInIdxMsg2());
}

View File

@ -1,705 +0,0 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2014 - 2021 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.keywordsearch;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import javax.annotation.concurrent.GuardedBy;
import javax.swing.SwingUtilities;
import javax.swing.SwingWorker;
import org.netbeans.api.progress.ProgressHandle;
import org.openide.util.Cancellable;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
import org.sleuthkit.autopsy.core.RuntimeProperties;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
import org.sleuthkit.autopsy.coreutils.StopWatch;
import org.sleuthkit.autopsy.coreutils.ThreadConfined;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestServices;
/**
* Performs periodic and final keyword searches for ingest jobs. Periodic
* searches are done in background tasks. This represents a careful working
* around of the contract for IngestModule.process(). Final searches are done
* synchronously in the calling thread, as required by the contract for
* IngestModule.shutDown().
*/
final class IngestSearchRunner {
private static final Logger logger = Logger.getLogger(IngestSearchRunner.class.getName());
private static IngestSearchRunner instance = null;
private final IngestServices services = IngestServices.getInstance();
private Ingester ingester = null;
private long currentUpdateIntervalMs;
private volatile boolean periodicSearchTaskRunning;
private volatile Future<?> periodicSearchTaskHandle;
private final ScheduledThreadPoolExecutor periodicSearchTaskExecutor;
private static final int NUM_SEARCH_SCHEDULING_THREADS = 1;
private static final String SEARCH_SCHEDULER_THREAD_NAME = "periodic-search-scheduling-%d";
private final Map<Long, SearchJobInfo> jobs = new ConcurrentHashMap<>(); // Ingest job ID to search job info
private final boolean usingNetBeansGUI = RuntimeProperties.runningWithGUI();
/*
* Constructs a singleton object that performs periodic and final keyword
* searches for ingest jobs. Periodic searches are done in background tasks.
* This represents a careful working around of the contract for
* IngestModule.process(). Final searches are done synchronously in the
* calling thread, as required by the contract for IngestModule.shutDown().
*/
private IngestSearchRunner() {
currentUpdateIntervalMs = ((long) KeywordSearchSettings.getUpdateFrequency().getTime()) * 60 * 1000;
ingester = Ingester.getDefault();
periodicSearchTaskExecutor = new ScheduledThreadPoolExecutor(NUM_SEARCH_SCHEDULING_THREADS, new ThreadFactoryBuilder().setNameFormat(SEARCH_SCHEDULER_THREAD_NAME).build());
}
/**
* Gets the ingest search runner singleton.
*
* @return The ingest search runner.
*/
public static synchronized IngestSearchRunner getInstance() {
if (instance == null) {
instance = new IngestSearchRunner();
}
return instance;
}
/**
* Starts the search job for an ingest job.
*
* @param jobContext The ingest job context.
* @param keywordListNames The names of the keyword search lists for the
* ingest job.
*/
public synchronized void startJob(IngestJobContext jobContext, List<String> keywordListNames) {
long jobId = jobContext.getJobId();
if (jobs.containsKey(jobId) == false) {
SearchJobInfo jobData = new SearchJobInfo(jobContext, keywordListNames);
jobs.put(jobId, jobData);
}
/*
* Keep track of the number of keyword search file ingest modules that
* are doing analysis for the ingest job, i.e., that have called this
* method. This is needed by endJob().
*/
jobs.get(jobId).incrementModuleReferenceCount();
/*
* Start a periodic search task in the
*/
if ((jobs.size() > 0) && (periodicSearchTaskRunning == false)) {
currentUpdateIntervalMs = ((long) KeywordSearchSettings.getUpdateFrequency().getTime()) * 60 * 1000;
periodicSearchTaskHandle = periodicSearchTaskExecutor.schedule(new PeriodicSearchTask(), currentUpdateIntervalMs, MILLISECONDS);
periodicSearchTaskRunning = true;
}
}
/**
* Finishes a search job for an ingest job.
*
* @param jobId The ingest job ID.
*/
public synchronized void endJob(long jobId) {
/*
* Only complete the job if this is the last keyword search file ingest
* module doing annalysis for this job.
*/
SearchJobInfo job;
job = jobs.get(jobId);
if (job == null) {
return; // RJCTODO: SEVERE
}
if (job.decrementModuleReferenceCount() != 0) {
jobs.remove(jobId);
}
/*
* Commit the index and do the final search. The final search is done in
* the ingest thread that shutDown() on the keyword search file ingest
* module, per the contract of IngestModule.shutDwon().
*/
logger.log(Level.INFO, "Commiting search index before final search for search job {0}", job.getJobId()); //NON-NLS
commit();
logger.log(Level.INFO, "Starting final search for search job {0}", job.getJobId()); //NON-NLS
doFinalSearch(job);
logger.log(Level.INFO, "Final search for search job {0} completed", job.getJobId()); //NON-NLS
if (jobs.isEmpty()) {
cancelPeriodicSearchSchedulingTask();
}
}
/**
* Stops the search job for an ingest job.
*
* @param jobId The ingest job ID.
*/
public synchronized void stopJob(long jobId) {
logger.log(Level.INFO, "Stopping search job {0}", jobId); //NON-NLS
commit();
SearchJobInfo job;
job = jobs.get(jobId);
if (job == null) {
return;
}
/*
* Request cancellation of the current keyword search, whether it is a
* preiodic search or a final search.
*/
IngestSearchRunner.Searcher currentSearcher = job.getCurrentSearcher();
if ((currentSearcher != null) && (!currentSearcher.isDone())) {
logger.log(Level.INFO, "Cancelling search job {0}", jobId); //NON-NLS
currentSearcher.cancel(true);
}
jobs.remove(jobId);
if (jobs.isEmpty()) {
cancelPeriodicSearchSchedulingTask();
}
}
/**
* Adds the given keyword list names to the set of keyword lists to be
* searched by ALL keyword search jobs. This supports adding one or more
* keyword search lists to ingest jobs already in progress.
*
* @param keywordListNames The n ames of the additional keyword lists.
*/
public synchronized void addKeywordListsToAllJobs(List<String> keywordListNames) {
for (String listName : keywordListNames) {
logger.log(Level.INFO, "Adding keyword list {0} to all jobs", listName); //NON-NLS
for (SearchJobInfo j : jobs.values()) {
j.addKeywordListName(listName);
}
}
}
/**
* Commits the Solr index for the current case and publishes an event
* indicating the current number of indexed items (this is no longer just
* files).
*/
private void commit() {
ingester.commit();
/*
* Publish an event advertising the number of indexed items. Note that
* this is no longer the number of indexed files, since the text of many
* items in addition to files is indexed.
*/
try {
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
KeywordSearch.fireNumIndexedFilesChange(null, numIndexedFiles);
} catch (NoOpenCoreException | KeywordSearchModuleException ex) {
logger.log(Level.SEVERE, "Error executing Solr query for number of indexed files", ex); //NON-NLS
}
}
/**
* Performs the final keyword search for an ingest job. The search is done
* synchronously, as required by the contract for IngestModule.shutDown().
*
* @param job The keyword search job info.
*/
private void doFinalSearch(SearchJobInfo job) {
if (!job.getKeywordListNames().isEmpty()) {
try {
/*
* Wait for any periodic searches being done in a SwingWorker
* pool thread to finish.
*/
job.waitForCurrentWorker();
IngestSearchRunner.Searcher finalSearcher = new IngestSearchRunner.Searcher(job, true);
job.setCurrentSearcher(finalSearcher);
/*
* Do the final search synchronously on the current ingest
* thread, per the contract specified
*/
finalSearcher.doInBackground();
} catch (InterruptedException | CancellationException ex) {
logger.log(Level.INFO, "Final search for search job {0} interrupted or cancelled", job.getJobId()); //NON-NLS
} catch (Exception ex) {
logger.log(Level.SEVERE, String.format("Final search for search job %d failed", job.getJobId()), ex); //NON-NLS
}
}
}
/**
* Cancels the current periodic search scheduling task.
*/
private synchronized void cancelPeriodicSearchSchedulingTask() {
if (periodicSearchTaskHandle != null) {
logger.log(Level.INFO, "No more search jobs, stopping periodic search scheduling"); //NON-NLS
periodicSearchTaskHandle.cancel(true);
periodicSearchTaskRunning = false;
}
}
/**
* Task that runs in ScheduledThreadPoolExecutor to periodically start and
* wait for keyword search tasks for each keyword search job in progress.
* The keyword search tasks for individual ingest jobs are implemented as
* SwingWorkers to support legacy APIs.
*/
private final class PeriodicSearchTask implements Runnable {
@Override
public void run() {
/*
* If there are no more jobs or this task has been cancelled, exit.
*/
if (jobs.isEmpty() || periodicSearchTaskHandle.isCancelled()) {
logger.log(Level.INFO, "Periodic search scheduling task has been cancelled, exiting"); //NON-NLS
periodicSearchTaskRunning = false;
return;
}
/*
* Commit the Solr index for the current case before doing the
* searches.
*/
commit();
/*
* Do a keyword search for each ingest job in progress. When the
* searches are done, recalculate the "hold off" time between
* searches to prevent back-to-back periodic searches and schedule
* the nect periodic search task.
*/
final StopWatch stopWatch = new StopWatch();
stopWatch.start();
for (Iterator<Entry<Long, SearchJobInfo>> iterator = jobs.entrySet().iterator(); iterator.hasNext();) {
SearchJobInfo job = iterator.next().getValue();
if (periodicSearchTaskHandle.isCancelled()) {
logger.log(Level.INFO, "Periodic search scheduling task has been cancelled, exiting"); //NON-NLS
periodicSearchTaskRunning = false;
return;
}
if (!job.getKeywordListNames().isEmpty() && !job.isWorkerRunning()) {
logger.log(Level.INFO, "Starting periodic search for search job {0}", job.getJobId());
Searcher searcher = new Searcher(job, false);
job.setCurrentSearcher(searcher);
searcher.execute();
job.setWorkerRunning(true);
try {
searcher.get();
} catch (InterruptedException | ExecutionException ex) {
logger.log(Level.SEVERE, String.format("Error performing keyword search for ingest job %d", job.getJobId()), ex); //NON-NLS
services.postMessage(IngestMessage.createErrorMessage(
KeywordSearchModuleFactory.getModuleName(),
NbBundle.getMessage(this.getClass(), "SearchRunner.Searcher.done.err.msg"), ex.getMessage()));
} catch (java.util.concurrent.CancellationException ex) {
logger.log(Level.SEVERE, String.format("Keyword search for ingest job %d cancelled", job.getJobId()), ex); //NON-NLS
}
}
}
stopWatch.stop();
logger.log(Level.INFO, "Periodic searches for all ingest jobs cumulatively took {0} secs", stopWatch.getElapsedTimeSecs()); //NON-NLS
recalculateUpdateIntervalTime(stopWatch.getElapsedTimeSecs()); // ELDEBUG
periodicSearchTaskHandle = periodicSearchTaskExecutor.schedule(new PeriodicSearchTask(), currentUpdateIntervalMs, MILLISECONDS);
}
/**
* Sets the time interval between periodic keyword searches to avoid
* running back-to-back searches. If the most recent round of searches
* took longer that 1/4 of the current interval, doubles the interval.
*
* @param lastSerchTimeSec The time in seconds used to execute the most
* recent round of keword searches.
*/
private void recalculateUpdateIntervalTime(long lastSerchTimeSec) {
if (lastSerchTimeSec * 1000 < currentUpdateIntervalMs / 4) {
return;
}
currentUpdateIntervalMs *= 2;
logger.log(Level.WARNING, "Last periodic search took {0} sec. Increasing search interval to {1} sec", new Object[]{lastSerchTimeSec, currentUpdateIntervalMs / 1000});
}
}
/**
* A data structure to keep track of the keyword lists, current results, and
* search running status for an ingest job.
*/
private class SearchJobInfo {
private final IngestJobContext jobContext;
private final long jobId;
private final long dataSourceId;
private volatile boolean workerRunning;
@GuardedBy("this")
private final List<String> keywordListNames;
@GuardedBy("this")
private final Map<Keyword, Set<Long>> currentResults; // Keyword to object IDs of items with hits
private IngestSearchRunner.Searcher currentSearcher;
private final AtomicLong moduleReferenceCount = new AtomicLong(0);
private final Object finalSearchLock = new Object();
private SearchJobInfo(IngestJobContext jobContext, List<String> keywordListNames) {
this.jobContext = jobContext;
jobId = jobContext.getJobId();
dataSourceId = jobContext.getDataSource().getId();
this.keywordListNames = new ArrayList<>(keywordListNames);
currentResults = new HashMap<>();
workerRunning = false;
currentSearcher = null;
}
private IngestJobContext getJobContext() {
return jobContext;
}
private long getJobId() {
return jobId;
}
private long getDataSourceId() {
return dataSourceId;
}
private synchronized List<String> getKeywordListNames() {
return new ArrayList<>(keywordListNames);
}
private synchronized void addKeywordListName(String keywordListName) {
if (!keywordListNames.contains(keywordListName)) {
keywordListNames.add(keywordListName);
}
}
private synchronized Set<Long> currentKeywordResults(Keyword k) {
return currentResults.get(k);
}
private synchronized void addKeywordResults(Keyword k, Set<Long> resultsIDs) {
currentResults.put(k, resultsIDs);
}
private boolean isWorkerRunning() {
return workerRunning;
}
private void setWorkerRunning(boolean flag) {
workerRunning = flag;
}
private synchronized IngestSearchRunner.Searcher getCurrentSearcher() {
return currentSearcher;
}
private synchronized void setCurrentSearcher(IngestSearchRunner.Searcher searchRunner) {
currentSearcher = searchRunner;
}
private void incrementModuleReferenceCount() {
moduleReferenceCount.incrementAndGet();
}
private long decrementModuleReferenceCount() {
return moduleReferenceCount.decrementAndGet();
}
/**
* Waits for the current search task to complete.
*
* @throws InterruptedException
*/
private void waitForCurrentWorker() throws InterruptedException {
synchronized (finalSearchLock) {
while (workerRunning) {
logger.log(Level.INFO, String.format("Waiting for previous search task for job %d to finish", jobId)); //NON-NLS
finalSearchLock.wait();
logger.log(Level.INFO, String.format("Notified previous search task for job %d to finish", jobId)); //NON-NLS
}
}
}
/**
* Signals any threads waiting on the current search task to complete.
*/
private void searchNotify() {
synchronized (finalSearchLock) {
workerRunning = false;
finalSearchLock.notify();
}
}
}
/*
* A SwingWorker responsible for searching the Solr index of the current
* case for the keywords for an ingest job. Keyword hit analysis results are
* created and posted to the blackboard and notifications are sent to the
* ingest inbox.
*/
private final class Searcher extends SwingWorker<Object, Void> {
/*
* Searcher has private copies/snapshots of the lists and keywords
*/
private final SearchJobInfo job;
private final List<Keyword> keywords; //keywords to search
private final List<String> keywordListNames; // lists currently being searched
private final List<KeywordList> keywordLists;
private final Map<Keyword, KeywordList> keywordToList; //keyword to list name mapping
@ThreadConfined(type = ThreadConfined.ThreadType.AWT)
private ProgressHandle progressIndicator;
private boolean finalRun = false;
Searcher(SearchJobInfo job, boolean finalRun) {
this.job = job;
this.finalRun = finalRun;
keywordListNames = job.getKeywordListNames();
keywords = new ArrayList<>();
keywordToList = new HashMap<>();
keywordLists = new ArrayList<>();
}
@Override
@Messages("SearchRunner.query.exception.msg=Error performing query:")
protected Object doInBackground() throws Exception {
try {
if (usingNetBeansGUI) {
/*
* If running in the NetBeans thick client application
* version of Autopsy, NetBeans progress handles (i.e.,
* progress bars) are used to display search progress in the
* lower right hand corner of the main application window.
*
* A layer of abstraction to allow alternate representations
* of progress could be used here, as it is in other places
* in the application (see implementations and usage of
* org.sleuthkit.autopsy.progress.ProgressIndicator
* interface), to better decouple keyword search from the
* application's presentation layer.
*/
SwingUtilities.invokeAndWait(() -> {
final String displayName = NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.displayName")
+ (finalRun ? (" - " + NbBundle.getMessage(this.getClass(), "KeywordSearchIngestModule.doInBackGround.finalizeMsg")) : "");
progressIndicator = ProgressHandle.createHandle(displayName, new Cancellable() {
@Override
public boolean cancel() {
if (progressIndicator != null) {
progressIndicator.setDisplayName(displayName + " " + NbBundle.getMessage(this.getClass(), "SearchRunner.doInBackGround.cancelMsg"));
}
logger.log(Level.INFO, "Search cancelled by user"); //NON-NLS
new Thread(() -> {
IngestSearchRunner.Searcher.this.cancel(true);
}).start();
return true;
}
});
progressIndicator.start();
progressIndicator.switchToIndeterminate();
});
}
updateKeywords();
for (Keyword keyword : keywords) {
if (isCancelled() || job.getJobContext().fileIngestIsCancelled()) {
logger.log(Level.INFO, "Cancellation requested, exiting before new keyword processed: {0}", keyword.getSearchTerm()); //NON-NLS
return null;
}
KeywordList keywordList = keywordToList.get(keyword);
if (usingNetBeansGUI) {
String searchTermStr = keyword.getSearchTerm();
if (searchTermStr.length() > 50) {
searchTermStr = searchTermStr.substring(0, 49) + "...";
}
final String progressMessage = keywordList.getName() + ": " + searchTermStr;
SwingUtilities.invokeLater(() -> {
progressIndicator.progress(progressMessage);
});
}
// Filtering
//limit search to currently ingested data sources
//set up a filter with 1 or more image ids OR'ed
KeywordSearchQuery keywordSearchQuery = KeywordSearchUtil.getQueryForKeyword(keyword, keywordList);
KeywordQueryFilter dataSourceFilter = new KeywordQueryFilter(KeywordQueryFilter.FilterType.DATA_SOURCE, job.getDataSourceId());
keywordSearchQuery.addFilter(dataSourceFilter);
// Do the actual search
QueryResults queryResults;
try {
queryResults = keywordSearchQuery.performQuery();
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
logger.log(Level.SEVERE, "Error performing query: " + keyword.getSearchTerm(), ex); //NON-NLS
if (usingNetBeansGUI) {
final String userMessage = Bundle.SearchRunner_query_exception_msg() + keyword.getSearchTerm();
SwingUtilities.invokeLater(() -> {
MessageNotifyUtil.Notify.error(userMessage, ex.getCause().getMessage());
});
}
//no reason to continue with next query if recovery failed
//or wait for recovery to kick in and run again later
//likely case has closed and threads are being interrupted
return null;
} catch (CancellationException e) {
logger.log(Level.INFO, "Cancellation requested, exiting during keyword query: {0}", keyword.getSearchTerm()); //NON-NLS
return null;
}
// Reduce the results of the query to only those hits we
// have not already seen.
QueryResults newResults = filterResults(queryResults);
if (!newResults.getKeywords().isEmpty()) {
// Create blackboard artifacts
newResults.process(this, keywordList.getIngestMessages(), true, job.getJobId());
}
}
} catch (Exception ex) {
logger.log(Level.SEVERE, String.format("Error performing keyword search for ingest job %d", job.getJobId()), ex); //NON-NLS
} finally {
if (progressIndicator != null) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
progressIndicator.finish();
progressIndicator = null;
}
});
}
// In case a thread is waiting on this worker to be done
job.searchNotify();
}
return null;
}
/**
* Sync-up the updated keywords from the currently used lists in the XML
*/
private void updateKeywords() {
XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
keywords.clear();
keywordToList.clear();
keywordLists.clear();
for (String name : keywordListNames) {
KeywordList list = loader.getList(name);
keywordLists.add(list);
for (Keyword k : list.getKeywords()) {
keywords.add(k);
keywordToList.put(k, list);
}
}
}
/**
* This method filters out all of the hits found in earlier periodic
* searches and returns only the results found by the most recent
* search.
*
* This method will only return hits for objects for which we haven't
* previously seen a hit for the keyword.
*
* @param queryResult The results returned by a keyword search.
*
* @return A unique set of hits found by the most recent search for
* objects that have not previously had a hit. The hits will be
* for the lowest numbered chunk associated with the object.
*
*/
private QueryResults filterResults(QueryResults queryResult) {
// Create a new (empty) QueryResults object to hold the most recently
// found hits.
QueryResults newResults = new QueryResults(queryResult.getQuery());
// For each keyword represented in the results.
for (Keyword keyword : queryResult.getKeywords()) {
// These are all of the hits across all objects for the most recent search.
// This may well include duplicates of hits we've seen in earlier periodic searches.
List<KeywordHit> queryTermResults = queryResult.getResults(keyword);
// Sort the hits for this keyword so that we are always
// guaranteed to return the hit for the lowest chunk.
Collections.sort(queryTermResults);
// This will be used to build up the hits we haven't seen before
// for this keyword.
List<KeywordHit> newUniqueHits = new ArrayList<>();
// Get the set of object ids seen in the past by this searcher
// for the given keyword.
Set<Long> curTermResults = job.currentKeywordResults(keyword);
if (curTermResults == null) {
// We create a new empty set if we haven't seen results for
// this keyword before.
curTermResults = new HashSet<>();
}
// For each hit for this keyword.
for (KeywordHit hit : queryTermResults) {
if (curTermResults.contains(hit.getSolrObjectId())) {
// Skip the hit if we've already seen a hit for
// this keyword in the object.
continue;
}
// We haven't seen the hit before so add it to list of new
// unique hits.
newUniqueHits.add(hit);
// Add the object id to the results we've seen for this
// keyword.
curTermResults.add(hit.getSolrObjectId());
}
// Update the job with the list of objects for which we have
// seen hits for the current keyword.
job.addKeywordResults(keyword, curTermResults);
// Add the new hits for the current keyword into the results
// to be returned.
newResults.addResult(keyword, newUniqueHits);
}
return newResults;
}
}
}

View File

@ -19,9 +19,14 @@
package org.sleuthkit.autopsy.keywordsearch;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
@ -29,9 +34,9 @@ import org.apache.commons.lang3.math.NumberUtils;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.common.SolrInputDocument;
import org.openide.util.NbBundle;
import org.openide.util.io.ReaderInputStream;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.TimeZoneUtils;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.healthmonitor.HealthMonitor;
import org.sleuthkit.autopsy.healthmonitor.TimingMetric;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
@ -146,10 +151,10 @@ class Ingester {
* @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException
*/
// TODO (JIRA-3118): Cancelled text indexing does not propagate cancellation to clients
< T extends SleuthkitVisitableItem> boolean indexText(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context) throws Ingester.IngesterException {
boolean doLanguageDetection = true;
return indexText(sourceReader, sourceID, sourceName, source, context, doLanguageDetection);
}
// < T extends SleuthkitVisitableItem> boolean search(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context, boolean indexIntoSolr, List<String> keywordListNames) throws Ingester.IngesterException {
// boolean doLanguageDetection = true;
// return search(sourceReader, sourceID, sourceName, source, context, doLanguageDetection, indexIntoSolr, keywordListNames);
// }
/**
* Read and chunk the source text for indexing in Solr. Does NOT perform
@ -170,11 +175,17 @@ class Ingester {
* @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException
*/
// TODO (JIRA-3118): Cancelled text indexing does not propagate cancellation to clients
< T extends SleuthkitVisitableItem> boolean indexStrings(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context) throws Ingester.IngesterException {
// Per JIRA-7100, it was determined that language detection on extracted strings can take a really long time.
boolean doLanguageDetection = false;
return indexText(sourceReader, sourceID, sourceName, source, context, doLanguageDetection);
}
// < T extends SleuthkitVisitableItem> boolean searchStrings(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context, boolean indexIntoSolr) throws Ingester.IngesterException {
// // Per JIRA-7100, it was determined that language detection on extracted strings can take a really long time.
// boolean doLanguageDetection = false;
// return search(sourceReader, sourceID, sourceName, source, context, doLanguageDetection, indexIntoSolr, null);
// }
//
// < T extends SleuthkitVisitableItem> boolean searchStrings(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context, boolean indexIntoSolr, List<String> keywordListNames) throws Ingester.IngesterException {
// // Per JIRA-7100, it was determined that language detection on extracted strings can take a really long time.
// boolean doLanguageDetection = false;
// return search(sourceReader, sourceID, sourceName, source, context, doLanguageDetection, indexIntoSolr, keywordListNames);
// }
/**
* Read and chunk the source text for indexing in Solr.
@ -195,60 +206,91 @@ class Ingester {
* @throws org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException
*/
// TODO (JIRA-3118): Cancelled text indexing does not propagate cancellation to clients
private < T extends SleuthkitVisitableItem> boolean indexText(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context, boolean doLanguageDetection) throws Ingester.IngesterException {
< T extends SleuthkitVisitableItem> void search(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context, boolean doLanguageDetection, boolean indexIntoSolr, List<String> keywordListNames) throws Ingester.IngesterException, IOException, TskCoreException, Exception {
int numChunks = 0; //unknown until chunking is done
Map<String, String> contentFields = Collections.unmodifiableMap(getContentFields(source));
Optional<Language> language = Optional.empty();
InlineSearcher searcher = new InlineSearcher(keywordListNames, context);
List<Chunk> activeChunkList = new ArrayList<>();
boolean fileIndexed = false;
//Get a reader for the content of the given source
try (BufferedReader reader = new BufferedReader(sourceReader)) {
Chunker chunker = new Chunker(reader);
String name = sourceName;
if(!(source instanceof BlackboardArtifact)) {
searcher.searchString(name, sourceID, 0);
}
while (chunker.hasNext()) {
if (context != null && context.fileIngestIsCancelled()) {
if ( context.fileIngestIsCancelled()) {
logger.log(Level.INFO, "File ingest cancelled. Cancelling keyword search indexing of {0}", sourceName);
return false;
return;
}
Chunk chunk = chunker.next();
Map<String, Object> fields = new HashMap<>(contentFields);
String chunkId = Server.getChunkIdString(sourceID, numChunks + 1);
fields.put(Server.Schema.ID.toString(), chunkId);
fields.put(Server.Schema.CHUNK_SIZE.toString(), String.valueOf(chunk.getBaseChunkLength()));
Chunk chunk = chunker.next();
chunk.setChunkId(numChunks+1);
if (doLanguageDetection) {
int size = Math.min(chunk.getBaseChunkLength(), LANGUAGE_DETECTION_STRING_SIZE);
language = languageSpecificContentIndexingHelper.detectLanguageIfNeeded(chunk.toString().substring(0, size));
// only do language detection on the first chunk of the document
doLanguageDetection = false;
}
language.ifPresent(lang -> languageSpecificContentIndexingHelper.updateLanguageSpecificFields(fields, chunk, lang));
try {
//add the chunk text to Solr index
indexChunk(chunk.toString(), chunk.geLowerCasedChunk(), sourceName, fields);
// add mini chunk when there's a language specific field
if (chunker.hasNext() && language.isPresent()) {
languageSpecificContentIndexingHelper.indexMiniChunk(chunk, sourceName, new HashMap<>(contentFields), chunkId, language.get());
if(keywordListNames != null) {
boolean hitFoundInChunk = searcher.searchChunk(chunk, sourceID, numChunks);
if(!indexIntoSolr) {
if(!hitFoundInChunk) {
if(!activeChunkList.isEmpty() ) {
if(activeChunkList.get(activeChunkList.size() - 1).hasHit()) {
activeChunkList.add(chunk);
// Write List
for(Chunk c: activeChunkList) {
indexChunk(c, sourceID, sourceName, language, contentFields, chunker.hasNext());
}
activeChunkList.clear();
} else {
activeChunkList.clear();
activeChunkList.add(chunk);
}
} else {
activeChunkList.add(chunk);
}
} else {
fileIndexed = true;
chunk.setHasHit(true);
activeChunkList.add(chunk);
}
} else {
indexChunk(chunk, sourceID, sourceName, language, contentFields, chunker.hasNext());
fileIndexed = true;
}
numChunks++;
} catch (Ingester.IngesterException ingEx) {
logger.log(Level.WARNING, "Ingester had a problem with extracted string from file '" //NON-NLS
+ sourceName + "' (id: " + sourceID + ").", ingEx);//NON-NLS
throw ingEx; //need to rethrow to signal error and move on
}
numChunks++;
}
if(activeChunkList.size() > 1 || (activeChunkList.size() == 1 && activeChunkList.get(0).hasHit())) {
for(Chunk c: activeChunkList) {
indexChunk(c, sourceID, sourceName, language, contentFields, true);
}
}
if (chunker.hasException()) {
logger.log(Level.WARNING, "Error chunking content from " + sourceID + ": " + sourceName, chunker.getException());
return false;
throw chunker.getException();
}
} catch (Exception ex) {
logger.log(Level.WARNING, "Unexpected error, can't read content stream from " + sourceID + ": " + sourceName, ex);//NON-NLS
return false;
} finally {
if (context != null && context.fileIngestIsCancelled()) {
return false;
} else {
} finally {
if (context.fileIngestIsCancelled()) {
return ;
}
if (fileIndexed) {
Map<String, Object> fields = new HashMap<>(contentFields);
//after all chunks, index just the meta data, including the numChunks, of the parent file
fields.put(Server.Schema.NUM_CHUNKS.toString(), Integer.toString(numChunks));
@ -259,8 +301,103 @@ class Ingester {
indexChunk(null, null, sourceName, fields);
}
}
}
< T extends SleuthkitVisitableItem> boolean indexFile(Reader sourceReader, long sourceID, String sourceName, T source, IngestJobContext context, boolean doLanguageDetection) throws Ingester.IngesterException {
int numChunks = 0; //unknown until chunking is done
Map<String, String> contentFields = Collections.unmodifiableMap(getContentFields(source));
Optional<Language> language = Optional.empty();
//Get a reader for the content of the given source
try (BufferedReader reader = new BufferedReader(sourceReader)) {
Chunker chunker = new Chunker(reader);
while (chunker.hasNext()) {
if ( context.fileIngestIsCancelled()) {
logger.log(Level.INFO, "File ingest cancelled. Cancelling keyword search indexing of {0}", sourceName);
return false;
}
Chunk chunk = chunker.next();
if (doLanguageDetection) {
int size = Math.min(chunk.getBaseChunkLength(), LANGUAGE_DETECTION_STRING_SIZE);
language = languageSpecificContentIndexingHelper.detectLanguageIfNeeded(chunk.toString().substring(0, size));
// only do language detection on the first chunk of the document
doLanguageDetection = false;
}
Map<String, Object> fields = new HashMap<>(contentFields);
String chunkId = Server.getChunkIdString(sourceID, numChunks + 1);
fields.put(Server.Schema.ID.toString(), chunkId);
fields.put(Server.Schema.CHUNK_SIZE.toString(), String.valueOf(chunk.getBaseChunkLength()));
language.ifPresent(lang -> languageSpecificContentIndexingHelper.updateLanguageSpecificFields(fields, chunk, lang));
try {
//add the chunk text to Solr index
indexChunk(chunk.toString(), chunk.getLowerCasedChunk(), sourceName, fields);
// add mini chunk when there's a language specific field
if (chunker.hasNext() && language.isPresent()) {
languageSpecificContentIndexingHelper.indexMiniChunk(chunk, sourceName, new HashMap<>(contentFields), chunkId, language.get());
}
numChunks++;
} catch (Ingester.IngesterException ingEx) {
logger.log(Level.WARNING, "Ingester had a problem with extracted string from file '" //NON-NLS
+ sourceName + "' (id: " + sourceID + ").", ingEx);//NON-NLS
throw ingEx; //need to rethrow to signal error and move on
}
}
if (chunker.hasException()) {
logger.log(Level.WARNING, "Error chunking content from " + sourceID + ": " + sourceName, chunker.getException());
return false;
}
} catch (Exception ex) {
logger.log(Level.WARNING, "Unexpected error, can't read content stream from " + sourceID + ": " + sourceName, ex);//NON-NLS
return false;
} finally {
if (context.fileIngestIsCancelled()) {
return false;
} else {
Map<String, Object> fields = new HashMap<>(contentFields);
//after all chunks, index just the meta data, including the numChunks, of the parent file
fields.put(Server.Schema.NUM_CHUNKS.toString(), Integer.toString(numChunks));
//reset id field to base document id
fields.put(Server.Schema.ID.toString(), Long.toString(sourceID));
//"parent" docs don't have chunk_size
fields.remove(Server.Schema.CHUNK_SIZE.toString());
indexChunk(null, null, sourceName, fields);
}
}
return true;
}
private void indexChunk(Chunk chunk, long sourceID, String sourceName, Optional<Language> language, Map<String, String> contentFields, boolean hasNext) throws IngesterException {
Map<String, Object> fields = new HashMap<>(contentFields);
String chunkId = Server.getChunkIdString(sourceID, chunk.getChunkId());
fields.put(Server.Schema.ID.toString(), chunkId);
fields.put(Server.Schema.CHUNK_SIZE.toString(), String.valueOf(chunk.getBaseChunkLength()));
language.ifPresent(lang -> languageSpecificContentIndexingHelper.updateLanguageSpecificFields(fields, chunk, lang));
try {
//add the chunk text to Solr index
indexChunk(chunk.toString(), chunk.getLowerCasedChunk(), sourceName, fields);
// add mini chunk when there's a language specific field
if (hasNext && language.isPresent()) {
languageSpecificContentIndexingHelper.indexMiniChunk(chunk, sourceName, new HashMap<>(contentFields), chunkId, language.get());
}
} catch (Ingester.IngesterException ingEx) {
logger.log(Level.WARNING, "Ingester had a problem with extracted string from file '" //NON-NLS
+ sourceName + "' (id: " + sourceID + ").", ingEx);//NON-NLS
throw ingEx; //need to rethrow to signal error and move on
}
}
/**
* Add one chunk as to the Solr index as a separate Solr document.

View File

@ -0,0 +1,619 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2022 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.keywordsearch;
import com.twelvemonkeys.lang.StringUtil;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.validator.routines.DomainValidator;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.keywordsearch.Chunker.Chunk;
import static org.sleuthkit.autopsy.keywordsearch.RegexQuery.CREDIT_CARD_NUM_PATTERN;
import org.sleuthkit.datamodel.Blackboard;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
final class InlineSearcher {
private final List<KeywordList> keywordList;
private static final int MIN_EMAIL_ADDR_LENGTH = 8;
private static final Logger logger = Logger.getLogger(InlineSearcher.class.getName());
private final IngestJobContext context;
static final Map<Long, List<UniqueKeywordHit>> uniqueHitMap = new ConcurrentHashMap<>();
static final Map<Long, Map<Long, Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>>>> uniqueHitMap2 = new ConcurrentHashMap<>();
// Uses mostly native java and the lucene api to search the a given chuck
// for Keywords. Create unique KeywordHits for any unique hit.
InlineSearcher(List<String> keywordListNames, IngestJobContext context) {
this.keywordList = new ArrayList<>();
this.context = context;
if (keywordListNames != null) {
XmlKeywordSearchList loader = XmlKeywordSearchList.getCurrent();
for (String name : keywordListNames) {
keywordList.add(loader.getList(name));
}
}
}
/**
* Search the chunk for the currently selected keywords.
*
* @param chunk
* @param sourceID
*
* @throws TskCoreException
*/
boolean searchChunk(Chunk chunk, long sourceID, int chunkId) throws TskCoreException {
return searchString(chunk.getLowerCasedChunk(), sourceID, chunkId);
}
/**
* Search a string for the currently selected keywords.
*
* @param text
* @param sourceID
*
* @throws TskCoreException
*/
boolean searchString(String text, long sourceID, int chunkId) throws TskCoreException {
boolean hitFound = false;
Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>> hitByKeyword = getMap(context.getJobId(), sourceID);
for (KeywordList list : keywordList) {
List<Keyword> keywords = list.getKeywords();
for (Keyword originalKeyword : keywords) {
Map<Keyword, List<UniqueKeywordHit>> hitMap = hitByKeyword.get(originalKeyword);
if (hitMap == null) {
hitMap = new HashMap<>();
hitByKeyword.put(originalKeyword, hitMap);
}
List<UniqueKeywordHit> keywordHits = new ArrayList<>();
if (originalKeyword.searchTermIsLiteral()) {
if (StringUtil.containsIgnoreCase(text, originalKeyword.getSearchTerm())) {
keywordHits.addAll(createKeywordHits(text, originalKeyword, sourceID, chunkId, list.getName()));
}
} else {
String regex = originalKeyword.getSearchTerm();
try {
// validate the regex
Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);
if (matcher.find()) {
keywordHits.addAll(createKeywordHits(text, originalKeyword, sourceID, chunkId, list.getName()));
}
} catch (IllegalArgumentException ex) {
//TODO What should we do here? Log and continue?
}
}
if (!keywordHits.isEmpty()) {
hitFound = true;
for (UniqueKeywordHit hit : keywordHits) {
Keyword keywordCopy = new Keyword(hit.getHit(),
originalKeyword.searchTermIsLiteral(),
originalKeyword.searchTermIsWholeWord(),
list.getName(),
originalKeyword.getOriginalTerm());
List<UniqueKeywordHit> mapHitList = hitMap.get(keywordCopy);
if (mapHitList == null) {
mapHitList = new ArrayList<>();
hitMap.put(keywordCopy, mapHitList);
}
if (!mapHitList.contains(hit)) {
mapHitList.add(hit);
}
}
}
if (context.fileIngestIsCancelled()) {
return hitFound;
}
}
}
return hitFound;
}
/**
* This method very similar to RegexQuery createKeywordHits, with the
* knowledge of solr removed.
*
* @param text
* @param originalKeyword
*
* @return A list of KeywordHit objects.
*
* @throws TskCoreException
*/
private List<UniqueKeywordHit> createKeywordHits(String text, Keyword originalKeyword, long sourceID, int chunkId, String keywordListName) throws TskCoreException {
if (originalKeyword.searchTermIsLiteral() && originalKeyword.searchTermIsWholeWord()) {
try {
return getExactMatchHits(text, originalKeyword, sourceID, chunkId, keywordListName);
} catch (IOException ex) {
throw new TskCoreException("Failed to create exactMatch hits", ex);
}
}
final HashMap<String, String> keywordsFoundInThisDocument = new HashMap<>();
List<UniqueKeywordHit> hits = new ArrayList<>();
String keywordString = originalKeyword.getSearchTerm();
boolean queryStringContainsWildcardSuffix = originalKeyword.getSearchTerm().endsWith(".*");
String searchPattern;
if (originalKeyword.searchTermIsLiteral()) {
/**
* For substring searches, the following pattern was arrived at
* through trial and error in an attempt to reproduce the same hits
* we were getting when we were using the TermComponent approach.
* This basically looks for zero of more word characters followed
* optionally by a dot or apostrophe, followed by the quoted
* lowercase substring following by zero or more word characters
* followed optionally by a dot or apostrophe. The reason that the
* dot and apostrophe characters are being handled here is because
* the old code used to find hits in domain names (e.g. hacks.ie)
* and possessives (e.g. hacker's). This obviously works for English
* but is probably not sufficient for other languages.
*/
searchPattern = "[\\w[\\.']]*" + java.util.regex.Pattern.quote(keywordString.toLowerCase()) + "[\\w[\\.']]*";
} else {
searchPattern = keywordString;
}
final java.util.regex.Pattern pattern = java.util.regex.Pattern.compile(searchPattern, Pattern.CASE_INSENSITIVE);
try {
String content = text;
Matcher hitMatcher = pattern.matcher(content);
int offset = 0;
while (hitMatcher.find(offset)) {
String hit = hitMatcher.group().toLowerCase();
/**
* No need to continue on if the the string is "" nothing to
* find or do.
*/
if ("".equals(hit)) {
break;
}
offset = hitMatcher.end();
final BlackboardAttribute.ATTRIBUTE_TYPE artifactAttributeType = originalKeyword.getArtifactAttributeType();
// We attempt to reduce false positives for phone numbers and IP address hits
// by querying Solr for hits delimited by a set of known boundary characters.
// See KeywordSearchList.PHONE_NUMBER_REGEX for an example.
// Because of this the hits may contain an extra character at the beginning or end that
// needs to be chopped off, unless the user has supplied their own wildcard suffix
// as part of the regex.
if (!queryStringContainsWildcardSuffix
&& (artifactAttributeType == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER
|| artifactAttributeType == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IP_ADDRESS)) {
if (artifactAttributeType == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER) {
// For phone numbers replace all non numeric characters (except "(") at the start of the hit.
hit = hit.replaceAll("^[^0-9\\(]", "");
} else {
// Replace all non numeric characters at the start of the hit.
hit = hit.replaceAll("^[^0-9]", "");
}
// Replace all non numeric at the end of the hit.
hit = hit.replaceAll("[^0-9]$", "");
if (offset > 1) {
/*
* NOTE: our IP and phone number regex patterns look for
* boundary characters immediately before and after the
* keyword hit. After a match, Java pattern mather
* re-starts at the first character not matched by the
* previous match. This basically requires two boundary
* characters to be present between each pattern match.
* To mitigate this we are resetting the offest one
* character back.
*/
offset--;
}
}
/**
* Boundary characters are removed from the start and end of the
* hit to normalize the hits. This is being done for substring
* searches only at this point. We don't do it for real regular
* expression searches because the user may have explicitly
* included boundary characters in their regular expression.
*/
if (originalKeyword.searchTermIsLiteral()) {
hit = hit.replaceAll("^" + KeywordSearchList.BOUNDARY_CHARACTERS + "*", "");
hit = hit.replaceAll(KeywordSearchList.BOUNDARY_CHARACTERS + "*$", "");
}
/**
* The use of String interning is an optimization to ensure that
* we reuse the same keyword hit String object across all hits.
* Even though we benefit from G1GC String deduplication, the
* overhead associated with creating a new String object for
* every KeywordHit can be significant when the number of hits
* gets large.
*/
hit = hit.intern();
// We will only create one KeywordHit instance per document for
// a given hit.
if (keywordsFoundInThisDocument.containsKey(hit)) {
continue;
}
keywordsFoundInThisDocument.put(hit, hit);
if (artifactAttributeType == null) {
hits.add(new UniqueKeywordHit(chunkId, sourceID, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit, keywordListName, originalKeyword.searchTermIsWholeWord(), originalKeyword.searchTermIsLiteral(), originalKeyword.getArtifactAttributeType(), originalKeyword.getSearchTerm()));
} else {
switch (artifactAttributeType) {
case TSK_EMAIL:
/*
* Reduce false positives by eliminating email
* address hits that are either too short or are not
* for valid top level domains.
*/
if (hit.length() >= MIN_EMAIL_ADDR_LENGTH
&& DomainValidator.getInstance(true).isValidTld(hit.substring(hit.lastIndexOf('.')))) {
hits.add(new UniqueKeywordHit(chunkId, sourceID, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit, keywordListName, originalKeyword.searchTermIsWholeWord(), originalKeyword.searchTermIsLiteral(), originalKeyword.getArtifactAttributeType(), originalKeyword.getSearchTerm()));
}
break;
case TSK_CARD_NUMBER:
/*
* If searching for credit card account numbers, do
* extra validation on the term and discard it if it
* does not pass.
*/
Matcher ccnMatcher = CREDIT_CARD_NUM_PATTERN.matcher(hit);
for (int rLength = hit.length(); rLength >= 12; rLength--) {
ccnMatcher.region(0, rLength);
if (ccnMatcher.find()) {
final String group = ccnMatcher.group("ccn");
if (CreditCardValidator.isValidCCN(group)) {
hits.add(new UniqueKeywordHit(chunkId, sourceID, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit, keywordListName, originalKeyword.searchTermIsWholeWord(), originalKeyword.searchTermIsLiteral(), originalKeyword.getArtifactAttributeType(), originalKeyword.getSearchTerm()));
}
}
}
break;
default:
hits.add(new UniqueKeywordHit(chunkId, sourceID, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit, keywordListName, originalKeyword.searchTermIsWholeWord(), originalKeyword.searchTermIsLiteral(), originalKeyword.getArtifactAttributeType(), originalKeyword.getSearchTerm()));
break;
}
}
}
} catch (Throwable error) {
/*
* NOTE: Matcher.find() is known to throw StackOverflowError in rare
* cases (see JIRA-2700). StackOverflowError is an error, not an
* exception, and therefore needs to be caught as a Throwable. When
* this occurs we should re-throw the error as TskCoreException so
* that it is logged by the calling method and move on to the next
* Solr document.
*/
throw new TskCoreException("Failed to create keyword hits for chunk due to " + error.getMessage());
}
return hits;
}
/**
* Clean up the memory that is being used for the given job.
*
* @param context
*/
static void cleanup(IngestJobContext context) {
Map<Long, Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>>> jobMap = uniqueHitMap2.get(context.getJobId());
if (jobMap != null) {
jobMap.clear();
}
}
/**
* Generates the artifacts for the found KeywordHits. This method should be
* called once per content object.
*
* @param context
*/
static void makeArtifacts(IngestJobContext context) throws TskException {
Map<Long, Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>>> jobMap = uniqueHitMap2.get(context.getJobId());
if (jobMap == null) {
return;
}
for (Map.Entry<Long, Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>>> mapBySource : jobMap.entrySet()) {
Long sourceId = mapBySource.getKey();
Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>> mapByKeyword = mapBySource.getValue();
for (Map.Entry<Keyword, Map<Keyword, List<UniqueKeywordHit>>> item : mapByKeyword.entrySet()) {
Keyword originalKeyword = item.getKey();
Map<Keyword, List<UniqueKeywordHit>> map = item.getValue();
List<BlackboardArtifact> hitArtifacts = new ArrayList<>();
if (!map.isEmpty()) {
for (Map.Entry<Keyword, List<UniqueKeywordHit>> entry : map.entrySet()) {
Keyword hitKeyword = entry.getKey();
List<UniqueKeywordHit> hitList = entry.getValue();
// Only create one hit for the document.
// The first hit in the list should be the first one that
// was found.
if (!hitList.isEmpty()) {
UniqueKeywordHit hit = hitList.get(0);
SleuthkitCase tskCase = Case.getCurrentCase().getSleuthkitCase();
Content content = tskCase.getContentById(hit.getContentID());
BlackboardArtifact artifact;
if (hit.isLiteral() && hit.isWholeWord()) {
artifact = LuceneQuery.createKeywordHitArtifact(content, originalKeyword, hitKeyword, hit, hit.getSnippet(), hitKeyword.getListName(), sourceId);
} else {
artifact = RegexQuery.createKeywordHitArtifact(content, originalKeyword, hitKeyword, hit, hit.getSnippet(), hitKeyword.getListName(), sourceId);
}
// createKeywordHitArtifact has the potential to return null
// when a CCN account is created.
if (artifact != null) {
hitArtifacts.add(artifact);
}
}
}
if (!hitArtifacts.isEmpty()) {
try {
SleuthkitCase tskCase = Case.getCurrentCaseThrows().getSleuthkitCase();
Blackboard blackboard = tskCase.getBlackboard();
blackboard.postArtifacts(hitArtifacts, "KeywordSearch", context.getJobId());
hitArtifacts.clear();
} catch (NoCurrentCaseException | Blackboard.BlackboardException ex) {
logger.log(Level.SEVERE, "Failed to post KWH artifact to blackboard.", ex); //NON-NLS
}
}
if (context.fileIngestIsCancelled()) {
return;
}
}
}
}
}
/**
* Searches the chunk for exact matches and creates the appropriate keyword
* hits.
*
* @param text
* @param originalKeyword
* @param sourceID
*
* @return
*
* @throws IOException
*/
public List<UniqueKeywordHit> getExactMatchHits(String text, Keyword originalKeyword, long sourceID, int chunkId, String keywordListName) throws IOException {
final HashMap<String, String> keywordsFoundInThisDocument = new HashMap<>();
List<UniqueKeywordHit> hits = new ArrayList<>();
Analyzer analyzer = new StandardAnalyzer();
//Get the tokens of the keyword
List<String> keywordTokens = new ArrayList<>();
try (TokenStream keywordstream = analyzer.tokenStream("field", originalKeyword.getSearchTerm())) {
CharTermAttribute attr = keywordstream.addAttribute(CharTermAttribute.class);
keywordstream.reset();
while (keywordstream.incrementToken()) {
keywordTokens.add(attr.toString());
}
}
try (TokenStream stream = analyzer.tokenStream("field", text)) {
CharTermAttribute attr = stream.addAttribute(CharTermAttribute.class);
OffsetAttribute offset = stream.addAttribute(OffsetAttribute.class);
stream.reset();
while (stream.incrementToken()) {
if (!attr.toString().equals(keywordTokens.get(0))) {
continue;
}
int startOffset = offset.startOffset();
int endOffset = offset.endOffset();
boolean match = true;
for (int index = 1; index < keywordTokens.size(); index++) {
if (stream.incrementToken()) {
if (!attr.toString().equals(keywordTokens.get(index))) {
match = false;
break;
} else {
endOffset = offset.endOffset();
}
}
}
if (match) {
String hit = text.subSequence(startOffset, endOffset).toString();
// We will only create one KeywordHit instance per document for
// a given hit.
if (keywordsFoundInThisDocument.containsKey(hit)) {
continue;
}
keywordsFoundInThisDocument.put(hit, hit);
hits.add(new UniqueKeywordHit(chunkId, sourceID, KeywordSearchUtil.makeSnippet(text, startOffset, endOffset, hit), hit, keywordListName, originalKeyword.searchTermIsWholeWord(), originalKeyword.searchTermIsLiteral(), originalKeyword.getArtifactAttributeType(), originalKeyword.getOriginalTerm()));
}
}
}
return hits;
}
/**
* Get the keyword map for the given job and source.
*
* @param jobId
* @param sourceID
*
* @return
*/
static private Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>> getMap(long jobId, long sourceID) {
Map<Long, Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>>> jobMap = uniqueHitMap2.get(jobId);
if (jobMap == null) {
jobMap = new ConcurrentHashMap<>();
uniqueHitMap2.put(jobId, jobMap);
}
Map<Keyword, Map<Keyword, List<UniqueKeywordHit>>> sourceMap = jobMap.get(sourceID);
if (sourceMap == null) {
sourceMap = new ConcurrentHashMap<>();
jobMap.put(sourceID, sourceMap);
}
return sourceMap;
}
// KeywordHit is not unique enough for finding duplicates, this class
// extends the KeywordHit class to make truely unique hits.
static class UniqueKeywordHit extends KeywordHit {
private final String listName;
private final boolean isLiteral;
private final boolean isWholeWord;
private final BlackboardAttribute.ATTRIBUTE_TYPE artifactAtrributeType;
private final String originalSearchTerm;
UniqueKeywordHit(int chunkId, long sourceID, String snippet, String hit, String listName, boolean isWholeWord, boolean isLiteral, BlackboardAttribute.ATTRIBUTE_TYPE artifactAtrributeType, String originalSearchTerm) {
super(chunkId, sourceID, snippet, hit);
this.listName = listName;
this.isWholeWord = isWholeWord;
this.isLiteral = isLiteral;
this.artifactAtrributeType = artifactAtrributeType;
this.originalSearchTerm = originalSearchTerm;
}
@Override
public int compareTo(KeywordHit other) {
return compare((UniqueKeywordHit) other);
}
private int compare(UniqueKeywordHit other) {
return Comparator.comparing(UniqueKeywordHit::getSolrObjectId)
.thenComparing(UniqueKeywordHit::getChunkId)
.thenComparing(UniqueKeywordHit::getHit)
.thenComparing(UniqueKeywordHit::getSnippet)
.thenComparing(UniqueKeywordHit::isWholeWord)
.thenComparing(UniqueKeywordHit::isLiteral)
.thenComparing(UniqueKeywordHit::getArtifactAtrributeType)
.thenComparing(UniqueKeywordHit::getOriginalSearchTerm)
.thenComparing(UniqueKeywordHit::getListName)
.compare(this, other);
}
@Override
public boolean equals(Object obj) {
if (null == obj) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final UniqueKeywordHit other = (UniqueKeywordHit) obj;
return getSnippet().equalsIgnoreCase(other.getSnippet())
&& getSolrObjectId().equals(other.getSolrObjectId())
&& getChunkId().equals(other.getChunkId())
&& getHit().equalsIgnoreCase(other.getHit())
&& listName.equalsIgnoreCase(other.getListName())
&& isLiteral == other.isLiteral()
&& isWholeWord == other.isWholeWord()
&& originalSearchTerm.equalsIgnoreCase(other.getOriginalSearchTerm())
&& (artifactAtrributeType != null ? artifactAtrributeType.equals(other.getArtifactAtrributeType()) : true);
}
@Override
public int hashCode() {
int hash = 3;
hash = 67 * hash + super.hashCode();
hash = 67 * hash + Objects.hashCode(this.listName);
hash = 67 * hash + (this.isLiteral ? 1 : 0);
hash = 67 * hash + (this.isWholeWord ? 1 : 0);
hash = 67 * hash + Objects.hashCode(this.artifactAtrributeType);
hash = 67 * hash + Objects.hashCode(this.originalSearchTerm);
return hash;
}
String getListName() {
return listName;
}
Boolean isLiteral() {
return isLiteral;
}
Boolean isWholeWord() {
return isWholeWord;
}
BlackboardAttribute.ATTRIBUTE_TYPE getArtifactAtrributeType() {
return artifactAtrributeType;
}
String getOriginalSearchTerm() {
return originalSearchTerm;
}
}
}

View File

@ -211,8 +211,10 @@ public class Keyword {
public int hashCode() {
int hash = 7;
hash = 17 * hash + this.searchTerm.hashCode();
hash = 17 * hash + this.listName.hashCode();
hash = 17 * hash + (this.isLiteral ? 1 : 0);
hash = 17 * hash + (this.isWholeWord ? 1 : 0);
hash = 17 * hash + this.originalTerm.hashCode();
return hash;
}

View File

@ -21,10 +21,12 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;
import org.apache.commons.lang3.StringUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.datamodel.TskCoreException;
@ -43,7 +45,7 @@ class KeywordHit implements Comparable<KeywordHit> {
private final int chunkId;
private final String snippet;
private final String hit;
/**
* Constructor
*
@ -54,7 +56,7 @@ class KeywordHit implements Comparable<KeywordHit> {
* For some searches (ie substring, regex) this will be
* different than the search term.
*
*/
*/
KeywordHit(String solrDocumentId, String snippet, String hit) {
this.snippet = StringUtils.stripToEmpty(snippet);
this.hit = hit;
@ -68,17 +70,30 @@ class KeywordHit implements Comparable<KeywordHit> {
* documents. One contains object metadata (chunk #1) and the second and
* subsequent documents contain chunks of the text.
*/
String[] split = solrDocumentId.split(Server.CHUNK_ID_SEPARATOR);
if (split.length == 1) {
//chunk 0 has only the bare document id without the chunk id.
this.solrObjectId = Long.parseLong(solrDocumentId);
this.chunkId = 0;
if(!solrDocumentId.isEmpty()) {
String[] split = solrDocumentId.split(Server.CHUNK_ID_SEPARATOR);
if (split.length == 1) {
//chunk 0 has only the bare document id without the chunk id.
this.solrObjectId = Long.parseLong(solrDocumentId);
this.chunkId = 0;
} else {
this.solrObjectId = Long.parseLong(split[0]);
this.chunkId = Integer.parseInt(split[1]);
}
} else {
this.solrObjectId = Long.parseLong(split[0]);
this.chunkId = Integer.parseInt(split[1]);
this.solrObjectId = 0;
this.chunkId = 0;
}
}
KeywordHit(int chunkId, long sourceID, String snippet, String hit) {
this.snippet = StringUtils.stripToEmpty(snippet);
this.hit = hit;
this.chunkId = chunkId;
this.solrObjectId = sourceID;
}
String getHit() {
return hit;
}
@ -87,11 +102,11 @@ class KeywordHit implements Comparable<KeywordHit> {
return Long.toString(solrObjectId) + Server.CHUNK_ID_SEPARATOR + Long.toString(chunkId);
}
long getSolrObjectId() {
Long getSolrObjectId() {
return this.solrObjectId;
}
int getChunkId() {
Integer getChunkId() {
return this.chunkId;
}
@ -102,7 +117,7 @@ class KeywordHit implements Comparable<KeywordHit> {
String getSnippet() {
return this.snippet;
}
/**
* Get the content id associated with the content underlying hit.
* For hits on files this will be the same as the object id associated
@ -172,20 +187,25 @@ class KeywordHit implements Comparable<KeywordHit> {
return false;
}
final KeywordHit other = (KeywordHit) obj;
return this.compareTo(other) == 0;
return compareTo(other) == 0;
}
@Override
public int hashCode() {
int hash = 3;
hash = 41 * hash + (int) this.solrObjectId + this.chunkId;
int hash = 7;
hash = 37 * hash + (int) (this.solrObjectId ^ (this.solrObjectId >>> 32));
hash = 37 * hash + this.chunkId;
hash = 37 * hash + Objects.hashCode(this.snippet);
hash = 37 * hash + Objects.hashCode(this.hit);
return hash;
}
@Override
public int compareTo(KeywordHit o) {
public int compareTo(KeywordHit other) {
return Comparator.comparing(KeywordHit::getSolrObjectId)
.thenComparing(KeywordHit::getChunkId)
.compare(this, o);
.thenComparing(KeywordHit::getHit)
.thenComparing(KeywordHit::getSnippet)
.compare(this, other);
}
}

View File

@ -1,10 +1,6 @@
<?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="timeGroup">
</Component>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
@ -47,23 +43,13 @@
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="filesIndexedValue" min="-2" max="-2" attributes="0"/>
</Group>
<Component id="frequencyLabel" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="chunksLabel" linkSize="1" min="-2" max="-2" attributes="0"/>
<EmptySpace type="separate" max="-2" attributes="0"/>
<Component id="chunksValLabel" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="16" pref="16" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="timeRadioButton2" min="-2" max="-2" attributes="0"/>
<Component id="timeRadioButton1" min="-2" max="-2" attributes="0"/>
<Component id="timeRadioButton3" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="timeRadioButton4" alignment="0" min="-2" max="-2" attributes="0"/>
<Component id="timeRadioButton5" alignment="0" min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace min="-2" pref="132" max="-2" attributes="0"/>
</Group>
</Group>
<EmptySpace max="32767" attributes="0"/>
@ -90,19 +76,7 @@
<Component id="skipNSRLCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="showSnippetsCB" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="frequencyLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeRadioButton1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeRadioButton2" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeRadioButton3" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeRadioButton4" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="timeRadioButton5" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Group type="103" groupAlignment="1" attributes="0">
<Component id="informationLabel" min="-2" max="-2" attributes="0"/>
<Component id="informationSeparator" min="-2" pref="7" max="-2" attributes="0"/>
@ -119,7 +93,7 @@
</Group>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="ingestWarningLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace max="32767" attributes="0"/>
<EmptySpace pref="151" max="32767" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
@ -184,65 +158,6 @@
</Component>
<Component class="javax.swing.JSeparator" name="informationSeparator">
</Component>
<Component class="javax.swing.JLabel" name="frequencyLabel">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
</Component>
<Component class="javax.swing.JRadioButton" name="timeRadioButton1">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeRadioButton1ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="timeRadioButton2">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeRadioButton2ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="timeRadioButton3">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeRadioButton3ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="timeRadioButton4">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeRadioButton4ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JCheckBox" name="showSnippetsCB">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
@ -253,19 +168,6 @@
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="showSnippetsCBActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JRadioButton" name="timeRadioButton5">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
<Property name="toolTipText" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="timeRadioButton5ActionPerformed"/>
</Events>
</Component>
<Component class="javax.swing.JLabel" name="ingestWarningLabel">
<Properties>
<Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2012-2018 Basis Technology Corp.
* Copyright 2012-2022 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -26,9 +26,7 @@ import org.netbeans.spi.options.OptionsPanelController;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.UpdateFrequency;
/**
* General, not per list, keyword search configuration and status display widget
@ -53,31 +51,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
boolean ingestRunning = IngestManager.getInstance().isIngestRunning();
ingestWarningLabel.setVisible(ingestRunning);
skipNSRLCheckBox.setEnabled(!ingestRunning);
setTimeSettingEnabled(!ingestRunning);
final UpdateFrequency curFreq = KeywordSearchSettings.getUpdateFrequency();
switch (curFreq) {
case FAST:
timeRadioButton1.setSelected(true);
break;
case AVG:
timeRadioButton2.setSelected(true);
break;
case SLOW:
timeRadioButton3.setSelected(true);
break;
case SLOWEST:
timeRadioButton4.setSelected(true);
break;
case NONE:
timeRadioButton5.setSelected(true);
break;
case DEFAULT:
default:
// default value
timeRadioButton3.setSelected(true);
break;
}
}
/**
@ -89,7 +62,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
timeGroup = new javax.swing.ButtonGroup();
skipNSRLCheckBox = new javax.swing.JCheckBox();
filesIndexedLabel = new javax.swing.JLabel();
filesIndexedValue = new javax.swing.JLabel();
@ -99,13 +71,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
informationLabel = new javax.swing.JLabel();
settingsSeparator = new javax.swing.JSeparator();
informationSeparator = new javax.swing.JSeparator();
frequencyLabel = new javax.swing.JLabel();
timeRadioButton1 = new javax.swing.JRadioButton();
timeRadioButton2 = new javax.swing.JRadioButton();
timeRadioButton3 = new javax.swing.JRadioButton();
timeRadioButton4 = new javax.swing.JRadioButton();
showSnippetsCB = new javax.swing.JCheckBox();
timeRadioButton5 = new javax.swing.JRadioButton();
ingestWarningLabel = new javax.swing.JLabel();
skipNSRLCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.skipNSRLCheckBox.text")); // NOI18N
@ -128,40 +94,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
informationLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.informationLabel.text")); // NOI18N
frequencyLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.frequencyLabel.text")); // NOI18N
timeRadioButton1.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.text")); // NOI18N
timeRadioButton1.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton1.toolTipText")); // NOI18N
timeRadioButton1.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeRadioButton1ActionPerformed(evt);
}
});
timeRadioButton2.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.text")); // NOI18N
timeRadioButton2.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton2.toolTipText")); // NOI18N
timeRadioButton2.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeRadioButton2ActionPerformed(evt);
}
});
timeRadioButton3.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.text")); // NOI18N
timeRadioButton3.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton3.toolTipText")); // NOI18N
timeRadioButton3.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeRadioButton3ActionPerformed(evt);
}
});
timeRadioButton4.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.text_1")); // NOI18N
timeRadioButton4.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton4.toolTipText")); // NOI18N
timeRadioButton4.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeRadioButton4ActionPerformed(evt);
}
});
showSnippetsCB.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.showSnippetsCB.text")); // NOI18N
showSnippetsCB.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
@ -169,14 +101,6 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
}
});
timeRadioButton5.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.text")); // NOI18N
timeRadioButton5.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.timeRadioButton5.toolTipText")); // NOI18N
timeRadioButton5.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
timeRadioButton5ActionPerformed(evt);
}
});
ingestWarningLabel.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/modules/hashdatabase/warning16.png"))); // NOI18N
ingestWarningLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchGlobalSearchSettingsPanel.class, "KeywordSearchGlobalSearchSettingsPanel.ingestWarningLabel.text")); // NOI18N
@ -207,19 +131,11 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addComponent(filesIndexedLabel)
.addGap(18, 18, 18)
.addComponent(filesIndexedValue))
.addComponent(frequencyLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(chunksLabel)
.addGap(18, 18, 18)
.addComponent(chunksValLabel))
.addGroup(layout.createSequentialGroup()
.addGap(16, 16, 16)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(timeRadioButton2)
.addComponent(timeRadioButton1)
.addComponent(timeRadioButton3)
.addComponent(timeRadioButton4)
.addComponent(timeRadioButton5))))))
.addComponent(chunksValLabel)))
.addGap(132, 132, 132)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(layout.createSequentialGroup()
.addComponent(settingsLabel)
@ -241,19 +157,7 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addComponent(skipNSRLCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(showSnippetsCB)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(frequencyLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeRadioButton1)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeRadioButton2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeRadioButton3)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeRadioButton4)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(timeRadioButton5)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(informationLabel)
.addComponent(informationSeparator, javax.swing.GroupLayout.PREFERRED_SIZE, 7, javax.swing.GroupLayout.PREFERRED_SIZE))
@ -267,14 +171,10 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
.addComponent(chunksValLabel))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ingestWarningLabel)
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap(151, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void timeRadioButton5ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton5ActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_timeRadioButton5ActionPerformed
private void skipNSRLCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_skipNSRLCheckBoxActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_skipNSRLCheckBoxActionPerformed
@ -283,28 +183,11 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_showSnippetsCBActionPerformed
private void timeRadioButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton1ActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_timeRadioButton1ActionPerformed
private void timeRadioButton2ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton2ActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_timeRadioButton2ActionPerformed
private void timeRadioButton3ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton3ActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_timeRadioButton3ActionPerformed
private void timeRadioButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_timeRadioButton4ActionPerformed
firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null);
}//GEN-LAST:event_timeRadioButton4ActionPerformed
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JLabel chunksLabel;
private javax.swing.JLabel chunksValLabel;
private javax.swing.JLabel filesIndexedLabel;
private javax.swing.JLabel filesIndexedValue;
private javax.swing.JLabel frequencyLabel;
private javax.swing.JLabel informationLabel;
private javax.swing.JSeparator informationSeparator;
private javax.swing.JLabel ingestWarningLabel;
@ -312,18 +195,11 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
private javax.swing.JSeparator settingsSeparator;
private javax.swing.JCheckBox showSnippetsCB;
private javax.swing.JCheckBox skipNSRLCheckBox;
private javax.swing.ButtonGroup timeGroup;
private javax.swing.JRadioButton timeRadioButton1;
private javax.swing.JRadioButton timeRadioButton2;
private javax.swing.JRadioButton timeRadioButton3;
private javax.swing.JRadioButton timeRadioButton4;
private javax.swing.JRadioButton timeRadioButton5;
// End of variables declaration//GEN-END:variables
@Override
public void store() {
KeywordSearchSettings.setSkipKnown(skipNSRLCheckBox.isSelected());
KeywordSearchSettings.setUpdateFrequency(getSelectedTimeValue());
KeywordSearchSettings.setShowSnippets(showSnippetsCB.isSelected());
}
@ -332,40 +208,10 @@ class KeywordSearchGlobalSearchSettingsPanel extends javax.swing.JPanel implemen
activateWidgets();
}
private void setTimeSettingEnabled(boolean enabled) {
timeRadioButton1.setEnabled(enabled);
timeRadioButton2.setEnabled(enabled);
timeRadioButton3.setEnabled(enabled);
timeRadioButton4.setEnabled(enabled);
timeRadioButton5.setEnabled(enabled);
frequencyLabel.setEnabled(enabled);
}
private UpdateFrequency getSelectedTimeValue() {
if (timeRadioButton1.isSelected()) {
return UpdateFrequency.FAST;
} else if (timeRadioButton2.isSelected()) {
return UpdateFrequency.AVG;
} else if (timeRadioButton3.isSelected()) {
return UpdateFrequency.SLOW;
} else if (timeRadioButton4.isSelected()) {
return UpdateFrequency.SLOWEST;
} else if (timeRadioButton5.isSelected()) {
return UpdateFrequency.NONE;
}
return UpdateFrequency.DEFAULT;
}
@NbBundle.Messages({"KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsOCR=Enable Optical Character Recognition (OCR) (Requires Windows 64-bit)",
"KeywordSearchGlobalSearchSettingsPanel.customizeComponents.windowsLimitedOCR=Only process images which are over 100KB in size or extracted from a document. (Beta) (Requires Windows 64-bit)"})
private void customizeComponents() {
timeGroup.add(timeRadioButton1);
timeGroup.add(timeRadioButton2);
timeGroup.add(timeRadioButton3);
timeGroup.add(timeRadioButton4);
timeGroup.add(timeRadioButton5);
this.skipNSRLCheckBox.setSelected(KeywordSearchSettings.getSkipKnown());
try {

View File

@ -1,7 +1,7 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2011-2021 Basis Technology Corp.
* Copyright 2011-2023 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.util.stream.Collectors;
import org.apache.tika.mime.MimeTypes;
import org.openide.util.Exceptions;
import org.openide.util.Lookup;
import org.openide.util.NbBundle;
import org.openide.util.NbBundle.Messages;
@ -69,6 +70,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskData;
import org.sleuthkit.datamodel.TskData.FileKnown;
import org.sleuthkit.datamodel.TskException;
/**
* An ingest module on a file level Performs indexing of allocated and Solr
@ -149,7 +151,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
.build();
private static final String IMAGE_MIME_TYPE_PREFIX = "image/";
// documents where OCR is performed
private static final ImmutableSet<String> OCR_DOCUMENTS = ImmutableSet.of(
"application/pdf",
@ -160,7 +162,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
/**
* Options for this extractor
*/
@ -169,33 +171,13 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
EXTRACT_UTF8, ///< extract UTF8 text, true/false
};
enum UpdateFrequency {
FAST(20),
AVG(10),
SLOW(5),
SLOWEST(1),
NONE(Integer.MAX_VALUE),
DEFAULT(5);
private final int time;
UpdateFrequency(int time) {
this.time = time;
}
int getTime() {
return time;
}
};
private static final Logger logger = Logger.getLogger(KeywordSearchIngestModule.class.getName());
private final IngestServices services = IngestServices.getInstance();
private Ingester ingester = null;
private Indexer indexer;
private FileTypeDetector fileTypeDetector;
//only search images from current ingest, not images previously ingested/indexed
//accessed read-only by searcher thread
private boolean startedSearching = false;
private Lookup stringsExtractionContext;
private final KeywordSearchJobSettings settings;
private boolean initialized = false;
@ -257,18 +239,21 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
initialized = false;
jobId = context.getJobId();
Server server = KeywordSearch.getServer();
if (server.coreIsOpen() == false) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startUp_noOpenCore_msg());
}
try {
Index indexInfo = server.getIndexInfo();
if (!indexInfo.isCompatible(IndexFinder.getCurrentSchemaVersion())) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion()));
Server server = null;
if (settings.isIndexToSolrEnabled()) {
server = KeywordSearch.getServer();
if (server.coreIsOpen() == false) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startUp_noOpenCore_msg());
}
try {
Index indexInfo = server.getIndexInfo();
if (!indexInfo.isCompatible(IndexFinder.getCurrentSchemaVersion())) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupException_indexSchemaNotSupported(indexInfo.getSchemaVersion()));
}
} catch (NoOpenCoreException ex) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupMessage_failedToGetIndexSchema(), ex);
}
} catch (NoOpenCoreException ex) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_startupMessage_failedToGetIndexSchema(), ex);
}
try {
@ -307,22 +292,24 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
}
} else {
// for single-user cases need to verify connection to local SOLR service
try {
if (!server.isLocalSolrRunning()) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg()));
// server will be null if indexing is disabled
if (server != null) {
try {
if (!server.isLocalSolrRunning()) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg()));
}
} catch (KeywordSearchModuleException ex) {
//this means Solr is not properly initialized
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg()), ex);
}
try {
// make an actual query to verify that server is responding
// we had cases where getStatus was OK, but the connection resulted in a 404
server.queryNumIndexedDocuments();
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_exception_errConnToSolr_msg(ex.getMessage()), ex);
}
} catch (KeywordSearchModuleException ex) {
//this means Solr is not properly initialized
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_tryStopSolrMsg(Bundle.KeywordSearchIngestModule_init_badInitMsg()), ex);
}
try {
// make an actual query to verify that server is responding
// we had cases where getStatus was OK, but the connection resulted in a 404
server.queryNumIndexedDocuments();
} catch (KeywordSearchModuleException | NoOpenCoreException ex) {
throw new IngestModuleException(Bundle.KeywordSearchIngestModule_init_exception_errConnToSolr_msg(ex.getMessage()), ex);
}
// check if this job has any searchable keywords
List<KeywordList> keywordLists = XmlKeywordSearchList.getCurrent().getListsL();
boolean hasKeywordsForSearch = false;
@ -347,7 +334,6 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
stringsExtractionContext = Lookups.fixed(stringsConfig);
indexer = new Indexer();
initialized = true;
}
@ -389,7 +375,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
if (context.fileIngestIsCancelled()) {
return ProcessResult.OK;
}
indexer.indexFile(extractorOpt, abstractFile, mimeType, false);
searchFile(extractorOpt, abstractFile, mimeType, false);
return ProcessResult.OK;
}
@ -397,17 +383,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
if (context.fileIngestIsCancelled()) {
return ProcessResult.OK;
}
indexer.indexFile(extractorOpt, abstractFile, mimeType, true);
// Start searching if it hasn't started already
if (!startedSearching) {
if (context.fileIngestIsCancelled()) {
return ProcessResult.OK;
}
List<String> keywordListNames = settings.getNamesOfEnabledKeyWordLists();
IngestSearchRunner.getInstance().startJob(context, keywordListNames);
startedSearching = true;
}
searchFile(extractorOpt, abstractFile, mimeType, true);
return ProcessResult.OK;
}
@ -425,17 +401,22 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
}
if (context.fileIngestIsCancelled()) {
logger.log(Level.INFO, "Keyword search ingest module instance {0} stopping search job due to ingest cancellation", instanceNum); //NON-NLS
IngestSearchRunner.getInstance().stopJob(jobId);
logger.log(Level.INFO, "Keyword search ingest module instance {0} stopping due to ingest cancellation", instanceNum); //NON-NLS
cleanup();
return;
}
// Remove from the search list and trigger final commit and final search
IngestSearchRunner.getInstance().endJob(jobId);
// We only need to post the summary msg from the last module per job
if (refCounter.decrementAndGet(jobId) == 0) {
try {
InlineSearcher.makeArtifacts(context);
InlineSearcher.cleanup(context);
Ingester.getDefault().commit();
} catch (TskException ex) {
logger.log(Level.SEVERE, String.format("Failed to create search ingest artifacts for job %d", context.getJobId()), ex);
}
try {
final int numIndexedFiles = KeywordSearch.getServer().queryNumIndexedFiles();
logger.log(Level.INFO, "Indexed files count: {0}", numIndexedFiles); //NON-NLS
@ -462,7 +443,7 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
}
/**
* Returns true if file should have OCR performed on it when limited OCR
* Returns true if file should have OCR performed on it when limited OCR
* setting is specified.
*
* @param aFile The abstract file.
@ -475,12 +456,12 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
if (OCR_DOCUMENTS.contains(mimeType)) {
return true;
}
if (mimeType.startsWith(IMAGE_MIME_TYPE_PREFIX)) {
return aFile.getSize() > LIMITED_OCR_SIZE_MIN
|| aFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED;
|| aFile.getType() == TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED;
}
return false;
}
@ -562,317 +543,319 @@ public final class KeywordSearchIngestModule implements FileIngestModule {
* File indexer, processes and indexes known/allocated files,
* unknown/unallocated files and directories accordingly
*/
private class Indexer {
private final Logger logger = Logger.getLogger(Indexer.class.getName());
/**
* Extract text with Tika or other text extraction modules (by
* streaming) from the file Divide the file into chunks and index the
* chunks
*
* @param extractorOptional The textExtractor to use with this file or
* empty.
* @param aFile file to extract strings from, divide into
* chunks and index
* @param extractedMetadata Map that will be populated with the file's
* metadata.
*
* @return true if the file was text_ingested, false otherwise
*
* @throws IngesterException exception thrown if indexing failed
*/
private boolean extractTextAndIndex(Optional<TextExtractor> extractorOptional, AbstractFile aFile,
/**
* Extract text with Tika or other text extraction modules (by streaming)
* from the file Divide the file into chunks and index the chunks
*
* @param extractorOptional The textExtractor to use with this file or
* empty.
* @param aFile file to extract strings from, divide into chunks
* and index
* @param extractedMetadata Map that will be populated with the file's
* metadata.
*
* @return true if the file was text_ingested, false otherwise
*
* @throws IngesterException exception thrown if indexing failed
*/
private boolean extractTextAndSearch(Optional<TextExtractor> extractorOptional, AbstractFile aFile,
Map<String, String> extractedMetadata) throws IngesterException {
try {
if (!extractorOptional.isPresent()) {
return false;
}
TextExtractor extractor = extractorOptional.get();
Reader fileText = extractor.getReader();
Reader finalReader;
try {
Map<String, String> metadata = extractor.getMetadata();
if (!metadata.isEmpty()) {
// Creating the metadata artifact here causes occasional problems
// when indexing the text, so we save the metadata map to
// use after this method is complete.
extractedMetadata.putAll(metadata);
}
CharSource formattedMetadata = getMetaDataCharSource(metadata);
//Append the metadata to end of the file text
finalReader = CharSource.concat(new CharSource() {
//Wrap fileText reader for concatenation
@Override
public Reader openStream() throws IOException {
return fileText;
}
}, formattedMetadata).openStream();
} catch (IOException ex) {
logger.log(Level.WARNING, String.format("Could not format extracted metadata for file %s [id=%d]",
try {
if (!extractorOptional.isPresent()) {
return false;
}
//divide into chunks and index
Ingester.getDefault().search(getTikaOrTextExtractor(extractorOptional, aFile, extractedMetadata), aFile.getId(), aFile.getName(), aFile, context, true,settings.isIndexToSolrEnabled(), settings.getNamesOfEnabledKeyWordLists());
} catch (TextExtractor.InitReaderException ex) {
return false;
} catch(Exception ex) {
logger.log(Level.WARNING, String.format("Failed to search file %s [id=%d]",
aFile.getName(), aFile.getId()), ex);
//Just send file text.
finalReader = fileText;
}
//divide into chunks and index
return Ingester.getDefault().indexText(finalReader, aFile.getId(), aFile.getName(), aFile, context);
} catch (TextExtractor.InitReaderException ex) {
// Text extractor could not be initialized. No text will be extracted.
return false;
}
return false;
}
private void createMetadataArtifact(AbstractFile aFile, Map<String, String> metadata) {
String moduleName = KeywordSearchIngestModule.class.getName();
Collection<BlackboardAttribute> attributes = new ArrayList<>();
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (Map.Entry<String, String> entry : metadata.entrySet()) {
if (METADATA_TYPES_MAP.containsKey(entry.getKey())) {
BlackboardAttribute bba = checkAttribute(entry.getKey(), entry.getValue());
if (bba != null) {
attributes.add(bba);
}
}
}
if (!attributes.isEmpty()) {
try {
BlackboardArtifact bbart = aFile.newDataArtifact(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA), attributes);
bbartifacts.add(bbart);
} catch (TskCoreException ex) {
// Log error and return to continue processing
logger.log(Level.WARNING, String.format("Error creating or adding metadata artifact for file %s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS
return;
}
if (!bbartifacts.isEmpty()) {
try {
Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().postArtifacts(bbartifacts, moduleName, jobId);
} catch (NoCurrentCaseException | Blackboard.BlackboardException ex) {
// Log error and return to continue processing
logger.log(Level.WARNING, String.format("Unable to post blackboard artifacts for file $s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS
return;
}
}
}
}
private BlackboardAttribute checkAttribute(String key, String value) {
String moduleName = KeywordSearchIngestModule.class.getName();
if (!value.isEmpty() && value.charAt(0) != ' ') {
if (METADATA_DATE_TYPES.contains(key)) {
SimpleDateFormat metadataDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", US);
Long metadataDateTime = Long.valueOf(0);
try {
String metadataDate = value.replaceAll("T", " ").replaceAll("Z", "");
Date usedDate = metadataDateFormat.parse(metadataDate);
metadataDateTime = usedDate.getTime() / 1000;
return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, metadataDateTime);
} catch (ParseException ex) {
// catching error and displaying date that could not be parsed then will continue on.
logger.log(Level.WARNING, String.format("Failed to parse date/time %s for metadata attribute %s.", value, key), ex); //NON-NLS
return null;
}
} else {
return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, value);
}
}
return null;
}
/**
* Pretty print the text extractor metadata.
*
* @param metadata The Metadata map to wrap as a CharSource
*
* @return A CharSource for the given Metadata
*/
@NbBundle.Messages({
"KeywordSearchIngestModule.metadataTitle=METADATA"
})
private CharSource getMetaDataCharSource(Map<String, String> metadata) {
return CharSource.wrap(new StringBuilder(
String.format("\n\n------------------------------%s------------------------------\n\n",
Bundle.KeywordSearchIngestModule_metadataTitle()))
.append(metadata.entrySet().stream().sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getKey() + ": " + entry.getValue())
.collect(Collectors.joining("\n"))
));
}
/**
* Extract strings using heuristics from the file and add to index.
*
* @param aFile file to extract strings from, divide into chunks and
* index
*
* @return true if the file was text_ingested, false otherwise
*/
private boolean extractStringsAndIndex(AbstractFile aFile) {
return true;
}
private Reader getTikaOrTextExtractor(Optional<TextExtractor> extractorOptional, AbstractFile aFile,
Map<String, String> extractedMetadata) throws TextExtractor.InitReaderException {
TextExtractor extractor = extractorOptional.get();
Reader fileText = extractor.getReader();
Reader finalReader;
try {
if (context.fileIngestIsCancelled()) {
return true;
Map<String, String> metadata = extractor.getMetadata();
if (!metadata.isEmpty()) {
// Creating the metadata artifact here causes occasional problems
// when indexing the text, so we save the metadata map to
// use after this method is complete.
extractedMetadata.putAll(metadata);
}
TextExtractor stringsExtractor = TextExtractorFactory.getStringsExtractor(aFile, stringsExtractionContext);
Reader extractedTextReader = stringsExtractor.getReader();
if (Ingester.getDefault().indexStrings(extractedTextReader, aFile.getId(), aFile.getName(), aFile, KeywordSearchIngestModule.this.context)) {
putIngestStatus(jobId, aFile.getId(), IngestStatus.STRINGS_INGESTED);
return true;
} else {
logger.log(Level.WARNING, "Failed to extract strings and ingest, file ''{0}'' (id: {1}).", new Object[]{aFile.getName(), aFile.getId()}); //NON-NLS
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
return false;
CharSource formattedMetadata = getMetaDataCharSource(metadata);
//Append the metadata to end of the file text
finalReader = CharSource.concat(new CharSource() {
//Wrap fileText reader for concatenation
@Override
public Reader openStream() throws IOException {
return fileText;
}
}, formattedMetadata).openStream();
} catch (IOException ex) {
logger.log(Level.WARNING, String.format("Could not format extracted metadata for file %s [id=%d]",
aFile.getName(), aFile.getId()), ex);
//Just send file text.
finalReader = fileText;
}
//divide into chunks and index
return finalReader;
}
private void createMetadataArtifact(AbstractFile aFile, Map<String, String> metadata) {
String moduleName = KeywordSearchIngestModule.class.getName();
Collection<BlackboardAttribute> attributes = new ArrayList<>();
Collection<BlackboardArtifact> bbartifacts = new ArrayList<>();
for (Map.Entry<String, String> entry : metadata.entrySet()) {
if (METADATA_TYPES_MAP.containsKey(entry.getKey())) {
BlackboardAttribute bba = checkAttribute(entry.getKey(), entry.getValue());
if (bba != null) {
attributes.add(bba);
}
} catch (IngesterException | TextExtractor.InitReaderException ex) {
logger.log(Level.WARNING, "Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId() + ").", ex); //NON-NLS
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
return false;
}
}
if (!attributes.isEmpty()) {
try {
BlackboardArtifact bbart = aFile.newDataArtifact(new BlackboardArtifact.Type(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA), attributes);
bbartifacts.add(bbart);
} catch (TskCoreException ex) {
// Log error and return to continue processing
logger.log(Level.WARNING, String.format("Error creating or adding metadata artifact for file %s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS
return;
}
if (!bbartifacts.isEmpty()) {
try {
Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboard().postArtifacts(bbartifacts, moduleName, jobId);
} catch (NoCurrentCaseException | Blackboard.BlackboardException ex) {
// Log error and return to continue processing
logger.log(Level.WARNING, String.format("Unable to post blackboard artifacts for file $s.", aFile.getParentPath() + aFile.getName()), ex); //NON-NLS
return;
}
}
}
}
private BlackboardAttribute checkAttribute(String key, String value) {
String moduleName = KeywordSearchIngestModule.class.getName();
if (!value.isEmpty() && value.charAt(0) != ' ') {
if (METADATA_DATE_TYPES.contains(key)) {
SimpleDateFormat metadataDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", US);
Long metadataDateTime = Long.valueOf(0);
try {
String metadataDate = value.replaceAll("T", " ").replaceAll("Z", "");
Date usedDate = metadataDateFormat.parse(metadataDate);
metadataDateTime = usedDate.getTime() / 1000;
return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, metadataDateTime);
} catch (ParseException ex) {
// catching error and displaying date that could not be parsed then will continue on.
logger.log(Level.WARNING, String.format("Failed to parse date/time %s for metadata attribute %s.", value, key), ex); //NON-NLS
return null;
}
} else {
return new BlackboardAttribute(METADATA_TYPES_MAP.get(key), moduleName, value);
}
}
return null;
}
/**
* Pretty print the text extractor metadata.
*
* @param metadata The Metadata map to wrap as a CharSource
*
* @return A CharSource for the given Metadata
*/
@NbBundle.Messages({
"KeywordSearchIngestModule.metadataTitle=METADATA"
})
private CharSource getMetaDataCharSource(Map<String, String> metadata) {
return CharSource.wrap(new StringBuilder(
String.format("\n\n------------------------------%s------------------------------\n\n",
Bundle.KeywordSearchIngestModule_metadataTitle()))
.append(metadata.entrySet().stream().sorted(Map.Entry.comparingByKey())
.map(entry -> entry.getKey() + ": " + entry.getValue())
.collect(Collectors.joining("\n"))
));
}
/**
* Extract strings using heuristics from the file and add to index.
*
* @param aFile file to extract strings from, divide into chunks and index
*
* @return true if the file was text_ingested, false otherwise
*/
private boolean extractStringsAndIndex(AbstractFile aFile) {
try {
if (context.fileIngestIsCancelled()) {
return true;
}
Reader extractedTextReader = KeywordSearchUtil.getReader(aFile, stringsExtractionContext);
Ingester.getDefault().search(extractedTextReader, aFile.getId(), aFile.getName(), aFile, KeywordSearchIngestModule.this.context, false, settings.isIndexToSolrEnabled(), settings.getNamesOfEnabledKeyWordLists());
putIngestStatus(jobId, aFile.getId(), IngestStatus.STRINGS_INGESTED);
} catch (Exception ex) {
logger.log(Level.WARNING, "Failed to extract strings and ingest, file '" + aFile.getName() + "' (id: " + aFile.getId() + ").", ex); //NON-NLS
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
return false;
}
return true;
}
/**
* Adds the file to the index. Detects file type, calls extractors, etc.
*
* @param extractor The textExtractor to use with this file or empty if
* no extractor found.
* @param aFile File to analyze.
* @param mimeType The file mime type.
* @param indexContent False if only metadata should be text_ingested. True
* if content and metadata should be index.
*/
private void searchFile(Optional<TextExtractor> extractor, AbstractFile aFile, String mimeType, boolean indexContent) {
//logger.log(Level.INFO, "Processing AbstractFile: " + abstractFile.getName());
TskData.TSK_DB_FILES_TYPE_ENUM aType = aFile.getType();
/**
* Adds the file to the index. Detects file type, calls extractors, etc.
*
* @param extractor The textExtractor to use with this file or empty
* if no extractor found.
* @param aFile File to analyze.
* @param mimeType The file mime type.
* @param indexContent False if only metadata should be text_ingested.
* True if content and metadata should be index.
* Extract unicode strings from unallocated and unused blocks and carved
* text files. The reason for performing string extraction on these is
* because they all may contain multiple encodings which can cause text
* to be missed by the more specialized text extractors used below.
*/
private void indexFile(Optional<TextExtractor> extractor, AbstractFile aFile, String mimeType, boolean indexContent) {
//logger.log(Level.INFO, "Processing AbstractFile: " + abstractFile.getName());
TskData.TSK_DB_FILES_TYPE_ENUM aType = aFile.getType();
/**
* Extract unicode strings from unallocated and unused blocks and
* carved text files. The reason for performing string extraction on
* these is because they all may contain multiple encodings which
* can cause text to be missed by the more specialized text
* extractors used below.
*/
if ((aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))
|| (aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED) && aFile.getNameExtension().equalsIgnoreCase("txt"))) {
if (context.fileIngestIsCancelled()) {
return;
}
extractStringsAndIndex(aFile);
return;
}
final long size = aFile.getSize();
//if not to index content, or a dir, or 0 content, index meta data only
if ((indexContent == false || aFile.isDir() || size == 0)) {
try {
if (context.fileIngestIsCancelled()) {
return;
}
ingester.indexMetaDataOnly(aFile);
putIngestStatus(jobId, aFile.getId(), IngestStatus.METADATA_INGESTED);
} catch (IngesterException ex) {
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); //NON-NLS
}
return;
}
if ((aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
|| aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS))
|| (aType.equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED) && aFile.getNameExtension().equalsIgnoreCase("txt"))) {
if (context.fileIngestIsCancelled()) {
return;
}
extractStringsAndIndex(aFile);
return;
}
// we skip archive formats that are opened by the archive module.
// @@@ We could have a check here to see if the archive module was enabled though...
if (ARCHIVE_MIME_TYPES.contains(mimeType)) {
try {
if (context.fileIngestIsCancelled()) {
return;
}
ingester.indexMetaDataOnly(aFile);
putIngestStatus(jobId, aFile.getId(), IngestStatus.METADATA_INGESTED);
} catch (IngesterException ex) {
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); //NON-NLS
}
return;
}
final long size = aFile.getSize();
//if not to index content, or a dir, or 0 content, index meta data only
boolean wasTextAdded = false;
Map<String, String> extractedMetadata = new HashMap<>();
//extract text with one of the extractors, divide into chunks and index with Solr
if ((indexContent == false || aFile.isDir() || size == 0)) {
try {
//logger.log(Level.INFO, "indexing: " + aFile.getName());
if (context.fileIngestIsCancelled()) {
return;
}
if (MimeTypes.OCTET_STREAM.equals(mimeType)) {
extractStringsAndIndex(aFile);
ingester.indexMetaDataOnly(aFile);
putIngestStatus(jobId, aFile.getId(), IngestStatus.METADATA_INGESTED);
} catch (IngesterException ex) {
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); //NON-NLS
}
return;
}
if (context.fileIngestIsCancelled()) {
return;
}
// we skip archive formats that are opened by the archive module.
// @@@ We could have a check here to see if the archive module was enabled though...
if (ARCHIVE_MIME_TYPES.contains(mimeType)) {
try {
if (context.fileIngestIsCancelled()) {
return;
}
if (!extractTextAndIndex(extractor, aFile, extractedMetadata)) {
// Text extractor not found for file. Extract string only.
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
} else {
putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
wasTextAdded = true;
}
} catch (IngesterException e) {
logger.log(Level.INFO, "Could not extract text with Tika, " + aFile.getId() + ", " //NON-NLS
+ aFile.getName(), e);
ingester.indexMetaDataOnly(aFile);
putIngestStatus(jobId, aFile.getId(), IngestStatus.METADATA_INGESTED);
} catch (IngesterException ex) {
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
} catch (Exception e) {
logger.log(Level.WARNING, "Error extracting text with Tika, " + aFile.getId() + ", " //NON-NLS
+ aFile.getName(), e);
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
}
if ((wasTextAdded == false) && (aFile.getNameExtension().equalsIgnoreCase("txt") && !(aFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED)))) {
//Carved Files should be the only type of unallocated files capable of a txt extension and
//should be ignored by the TextFileExtractor because they may contain more than one text encoding
wasTextAdded = indexTextFile(aFile);
}
// if it wasn't supported or had an error, default to strings
if (wasTextAdded == false) {
extractStringsAndIndex(aFile);
}
// Now that the indexing is complete, create the metadata artifact (if applicable).
// It is unclear why calling this from extractTextAndIndex() generates
// errors.
if (!extractedMetadata.isEmpty()) {
createMetadataArtifact(aFile, extractedMetadata);
logger.log(Level.WARNING, "Unable to index meta-data for file: " + aFile.getId(), ex); //NON-NLS
}
return;
}
/**
* Adds the text file to the index given an encoding. Returns true if
* indexing was successful and false otherwise.
*
* @param aFile Text file to analyze
*/
private boolean indexTextFile(AbstractFile aFile) {
try {
TextFileExtractor textFileExtractor = new TextFileExtractor(aFile);
Reader textReader = textFileExtractor.getReader();
if (textReader == null) {
logger.log(Level.INFO, "Unable to extract with TextFileExtractor, Reader was null for file: {0}", aFile.getName());
} else if (Ingester.getDefault().indexText(textReader, aFile.getId(), aFile.getName(), aFile, context)) {
textReader.close();
putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
return true;
}
} catch (IngesterException | IOException | TextExtractor.InitReaderException ex) {
logger.log(Level.WARNING, "Unable to index " + aFile.getName(), ex);
boolean wasTextAdded = false;
Map<String, String> extractedMetadata = new HashMap<>();
//extract text with one of the extractors, divide into chunks and index with Solr
try {
//logger.log(Level.INFO, "indexing: " + aFile.getName());
if (context.fileIngestIsCancelled()) {
return;
}
return false;
if (MimeTypes.OCTET_STREAM.equals(mimeType)) {
extractStringsAndIndex(aFile);
return;
}
if (!extractTextAndSearch(extractor, aFile, extractedMetadata)) {
// Text extractor not found for file. Extract string only.
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
} else {
putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
wasTextAdded = true;
}
} catch (IngesterException e) {
logger.log(Level.INFO, "Could not extract text with Tika, " + aFile.getId() + ", " //NON-NLS
+ aFile.getName(), e);
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_INDEXING);
} catch (Exception e) {
logger.log(Level.WARNING, "Error extracting text with Tika, " + aFile.getId() + ", " //NON-NLS
+ aFile.getName(), e);
putIngestStatus(jobId, aFile.getId(), IngestStatus.SKIPPED_ERROR_TEXTEXTRACT);
}
if ((wasTextAdded == false) && (aFile.getNameExtension().equalsIgnoreCase("txt") && !(aFile.getType().equals(TskData.TSK_DB_FILES_TYPE_ENUM.CARVED)))) {
//Carved Files should be the only type of unallocated files capable of a txt extension and
//should be ignored by the TextFileExtractor because they may contain more than one text encoding
wasTextAdded = searchTextFile(aFile);
}
// if it wasn't supported or had an error, default to strings
if (wasTextAdded == false) {
extractStringsAndIndex(aFile);
}
// Now that the indexing is complete, create the metadata artifact (if applicable).
// It is unclear why calling this from extractTextAndIndex() generates
// errors.
if (!extractedMetadata.isEmpty()) {
createMetadataArtifact(aFile, extractedMetadata);
}
}
/**
* Adds the text file to the index given an encoding. Returns true if
* indexing was successful and false otherwise.
*
* @param aFile Text file to analyze
*/
private boolean searchTextFile(AbstractFile aFile) {
try {
TextFileExtractor textFileExtractor = new TextFileExtractor(aFile);
Reader textReader = textFileExtractor.getReader();
if (textReader == null) {
logger.log(Level.INFO, "Unable to extract with TextFileExtractor, Reader was null for file: {0}", aFile.getName());
} else {
Ingester.getDefault().search(textReader, aFile.getId(), aFile.getName(), aFile, context, true, settings.isIndexToSolrEnabled(), settings.getNamesOfEnabledKeyWordLists());
textReader.close();
putIngestStatus(jobId, aFile.getId(), IngestStatus.TEXT_INGESTED);
return true;
}
} catch (Exception ex) {
logger.log(Level.WARNING, "Unable to index " + aFile.getName(), ex);
}
return false;
}
}

View File

@ -30,7 +30,7 @@ public final class KeywordSearchJobSettings implements IngestModuleIngestJobSett
private static final long serialVersionUID = 1L;
private HashSet<String> namesOfEnabledKeywordLists;
private final HashSet<String> namesOfEnabledKeywordLists;
private HashSet<String> namesOfDisabledKeywordLists; // Added in version 1.1
/**
@ -41,6 +41,8 @@ public final class KeywordSearchJobSettings implements IngestModuleIngestJobSett
private Boolean limitedOCREnabled;
private boolean ocrOnly;
private boolean indexToSolr;
/**
* Constructs ingest job settings for the keywords search module.
@ -55,6 +57,7 @@ public final class KeywordSearchJobSettings implements IngestModuleIngestJobSett
this.ocrEnabled = null;
this.limitedOCREnabled = null;
this.ocrOnly = false;
this.indexToSolr = true;
}
/**
@ -69,12 +72,13 @@ public final class KeywordSearchJobSettings implements IngestModuleIngestJobSett
* @param ocrOnly True if keyword search ingest should
* be solely limited to OCR.
*/
KeywordSearchJobSettings(List<String> namesOfEnabledKeywordLists, List<String> namesOfDisabledKeywordLists, boolean ocrEnabled, boolean limitedOCREnabled, boolean ocrOnly) {
KeywordSearchJobSettings(List<String> namesOfEnabledKeywordLists, List<String> namesOfDisabledKeywordLists, boolean ocrEnabled, boolean limitedOCREnabled, boolean ocrOnly, boolean indexToSolr) {
this.namesOfEnabledKeywordLists = new HashSet<>(namesOfEnabledKeywordLists);
this.namesOfDisabledKeywordLists = new HashSet<>(namesOfDisabledKeywordLists);
this.ocrEnabled = ocrEnabled;
this.limitedOCREnabled = limitedOCREnabled;
this.ocrOnly = ocrOnly;
this.indexToSolr = indexToSolr;
}
/**
@ -196,5 +200,13 @@ public final class KeywordSearchJobSettings implements IngestModuleIngestJobSett
this.namesOfDisabledKeywordLists = new HashSet<>();
}
}
boolean isIndexToSolrEnabled() {
return indexToSolr;
}
void setIndexToSolrEnabled(boolean enabled){
indexToSolr = enabled;
}
}

View File

@ -2,8 +2,11 @@
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<Properties>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 250]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 170]"/>
<Dimension value="[250, 250]"/>
</Property>
</Properties>
<AuxValues>
@ -16,70 +19,10 @@
<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"/>
<AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,0,-4,0,0,0,-6"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="1" attributes="0">
<Group type="102" attributes="0">
<EmptySpace max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="languagesLabel" alignment="1" max="32767" attributes="0"/>
<Group type="102" attributes="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="listsScrollPane" pref="316" max="32767" attributes="1"/>
<Component id="titleLabel" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<Component id="encodingsLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" max="-2" attributes="0"/>
<Component id="keywordSearchEncodings" min="-2" max="-2" attributes="0"/>
</Group>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="10" pref="10" max="-2" attributes="0"/>
<Component id="languagesValLabel" min="-2" pref="274" max="-2" attributes="0"/>
</Group>
<Component id="ocrCheckBox" alignment="0" min="-2" max="-2" attributes="0"/>
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="21" pref="21" max="-2" attributes="0"/>
<Group type="103" groupAlignment="0" attributes="0">
<Component id="ocrOnlyCheckbox" min="-2" max="-2" attributes="0"/>
<Component id="limitedOcrCheckbox" min="-2" pref="288" max="-2" attributes="0"/>
</Group>
</Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
</Group>
</Group>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Group type="102" alignment="0" attributes="0">
<EmptySpace min="-2" pref="7" max="-2" attributes="0"/>
<Component id="titleLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="listsScrollPane" max="32767" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="languagesLabel" min="-2" pref="13" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="languagesValLabel" min="-2" max="-2" attributes="0"/>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Group type="103" groupAlignment="3" attributes="0">
<Component id="encodingsLabel" alignment="3" min="-2" max="-2" attributes="0"/>
<Component id="keywordSearchEncodings" alignment="3" min="-2" max="-2" attributes="0"/>
</Group>
<EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/>
<Component id="ocrCheckBox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="ocrOnlyCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
<Component id="limitedOcrCheckbox" min="-2" max="-2" attributes="0"/>
<EmptySpace min="-2" max="-2" attributes="0"/>
</Group>
</Group>
</DimensionLayout>
</Layout>
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout"/>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="listsScrollPane">
<Properties>
@ -88,13 +31,21 @@
<EtchetBorder/>
</Border>
</Property>
<Property name="minimumSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[250, 48]"/>
</Property>
<Property name="preferredSize" type="java.awt.Dimension" editor="org.netbeans.beaninfo.editors.DimensionEditor">
<Dimension value="[300, 100]"/>
<Dimension value="[250, 48]"/>
</Property>
</Properties>
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="1" gridWidth="2" gridHeight="1" fill="1" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="1.0" weightY="1.0"/>
</Constraint>
</Constraints>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
@ -128,6 +79,11 @@
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchJobSettingsPanel.titleLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="0" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="languagesLabel">
<Properties>
@ -142,6 +98,11 @@
</Property>
<Property name="verticalTextPosition" type="int" value="3"/>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="2" gridWidth="2" gridHeight="1" fill="0" ipadX="25" ipadY="-22" insetsTop="2" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="languagesValLabel">
<Properties>
@ -152,6 +113,11 @@
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchJobSettingsPanel.languagesValLabel.toolTipText" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="3" gridWidth="2" gridHeight="1" fill="0" ipadX="270" ipadY="0" insetsTop="2" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="encodingsLabel">
<Properties>
@ -159,6 +125,11 @@
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchJobSettingsPanel.encodingsLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JLabel" name="keywordSearchEncodings">
<Properties>
@ -166,6 +137,11 @@
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchJobSettingsPanel.keywordSearchEncodings.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="1" gridY="4" gridWidth="1" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="5" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="ocrCheckBox">
<Properties>
@ -176,6 +152,11 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="ocrCheckBoxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="5" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="limitedOcrCheckbox">
<Properties>
@ -187,6 +168,11 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="limitedOcrCheckboxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="7" gridWidth="2" gridHeight="1" fill="0" ipadX="216" ipadY="0" insetsTop="0" insetsLeft="31" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="ocrOnlyCheckbox">
<Properties>
@ -197,6 +183,24 @@
<Events>
<EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="ocrOnlyCheckboxActionPerformed"/>
</Events>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="6" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="0" insetsLeft="31" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
<Component class="javax.swing.JCheckBox" name="solrCheckbox">
<Properties>
<Property name="selected" type="boolean" value="true"/>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
<ResourceString bundle="org/sleuthkit/autopsy/keywordsearch/Bundle.properties" key="KeywordSearchJobSettingsPanel.solrCheckbox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
</Property>
</Properties>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
<GridBagConstraints gridX="0" gridY="8" gridWidth="2" gridHeight="1" fill="0" ipadX="0" ipadY="0" insetsTop="2" insetsLeft="10" insetsBottom="0" insetsRight="0" anchor="18" weightX="0.0" weightY="0.0"/>
</Constraint>
</Constraints>
</Component>
</SubComponents>
</Form>

View File

@ -40,6 +40,8 @@ import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.StringsExtr
*/
@SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives
public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSettingsPanel implements PropertyChangeListener {
private static final long serialVersionUID = 1L;
private final KeywordListsTableModel tableModel = new KeywordListsTableModel();
private final List<String> keywordListNames = new ArrayList<>();
private final Map<String, Boolean> keywordListStates = new HashMap<>();
@ -65,6 +67,7 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
ocrCheckBox.setSelected(settings.isOCREnabled());
limitedOcrCheckbox.setSelected(settings.isLimitedOCREnabled());
ocrOnlyCheckbox.setSelected(settings.isOCROnly());
solrCheckbox.setSelected(settings.isIndexToSolrEnabled());
handleOcrEnabled(settings.isOCREnabled());
}
@ -194,7 +197,7 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
}
}
return new KeywordSearchJobSettings(enabledListNames, disabledListNames,
this.ocrCheckBox.isSelected(), this.limitedOcrCheckbox.isSelected(), this.ocrOnlyCheckbox.isSelected());
this.ocrCheckBox.isSelected(), this.limitedOcrCheckbox.isSelected(), this.ocrOnlyCheckbox.isSelected(), this.solrCheckbox.isSelected());
}
void reset(KeywordSearchJobSettings newSettings) {
@ -253,6 +256,7 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
listsScrollPane = new javax.swing.JScrollPane();
listsTable = new javax.swing.JTable();
@ -264,11 +268,15 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
ocrCheckBox = new javax.swing.JCheckBox();
limitedOcrCheckbox = new javax.swing.JCheckBox();
ocrOnlyCheckbox = new javax.swing.JCheckBox();
solrCheckbox = new javax.swing.JCheckBox();
setPreferredSize(new java.awt.Dimension(300, 170));
setMinimumSize(new java.awt.Dimension(250, 250));
setPreferredSize(new java.awt.Dimension(250, 250));
setLayout(new java.awt.GridBagLayout());
listsScrollPane.setBorder(javax.swing.BorderFactory.createEtchedBorder());
listsScrollPane.setPreferredSize(new java.awt.Dimension(300, 100));
listsScrollPane.setMinimumSize(new java.awt.Dimension(250, 48));
listsScrollPane.setPreferredSize(new java.awt.Dimension(250, 48));
listsTable.setBackground(new java.awt.Color(240, 240, 240));
listsTable.setModel(new javax.swing.table.DefaultTableModel(
@ -285,19 +293,66 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
listsScrollPane.setViewportView(listsTable);
listsTable.setDefaultRenderer(String.class, new SimpleTableCellRenderer());
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
gridBagConstraints.insets = new java.awt.Insets(2, 10, 0, 0);
add(listsScrollPane, gridBagConstraints);
titleLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.titleLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 0;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(2, 10, 0, 0);
add(titleLabel, gridBagConstraints);
languagesLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.languagesLabel.text")); // NOI18N
languagesLabel.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.languagesLabel.toolTipText")); // NOI18N
languagesLabel.setPreferredSize(new java.awt.Dimension(294, 35));
languagesLabel.setVerticalTextPosition(javax.swing.SwingConstants.BOTTOM);
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 2;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.ipadx = 25;
gridBagConstraints.ipady = -22;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(2, 10, 0, 0);
add(languagesLabel, gridBagConstraints);
languagesValLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.languagesValLabel.text")); // NOI18N
languagesValLabel.setToolTipText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.languagesValLabel.toolTipText")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 3;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.ipadx = 270;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(2, 10, 0, 0);
add(languagesValLabel, gridBagConstraints);
encodingsLabel.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.encodingsLabel.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 0);
add(encodingsLabel, gridBagConstraints);
keywordSearchEncodings.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.keywordSearchEncodings.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 4;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(5, 10, 0, 0);
add(keywordSearchEncodings, gridBagConstraints);
ocrCheckBox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.ocrCheckBox.text")); // NOI18N
ocrCheckBox.addActionListener(new java.awt.event.ActionListener() {
@ -305,6 +360,13 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
ocrCheckBoxActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 5;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(2, 10, 0, 0);
add(ocrCheckBox, gridBagConstraints);
limitedOcrCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.limitedOcrCheckbox.text")); // NOI18N
limitedOcrCheckbox.setVerticalTextPosition(javax.swing.SwingConstants.TOP);
@ -313,6 +375,14 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
limitedOcrCheckboxActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 7;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.ipadx = 216;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(0, 31, 0, 0);
add(limitedOcrCheckbox, gridBagConstraints);
ocrOnlyCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.ocrOnlyCheckbox.text")); // NOI18N
ocrOnlyCheckbox.addActionListener(new java.awt.event.ActionListener() {
@ -320,57 +390,23 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
ocrOnlyCheckboxActionPerformed(evt);
}
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 6;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(0, 31, 0, 0);
add(ocrOnlyCheckbox, gridBagConstraints);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(languagesLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(listsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 316, Short.MAX_VALUE)
.addComponent(titleLabel)
.addGroup(layout.createSequentialGroup()
.addComponent(encodingsLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(keywordSearchEncodings))
.addGroup(layout.createSequentialGroup()
.addGap(10, 10, 10)
.addComponent(languagesValLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 274, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(ocrCheckBox)
.addGroup(layout.createSequentialGroup()
.addGap(21, 21, 21)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(ocrOnlyCheckbox)
.addComponent(limitedOcrCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, 288, javax.swing.GroupLayout.PREFERRED_SIZE))))
.addContainerGap())))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(7, 7, 7)
.addComponent(titleLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(listsScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(languagesLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 13, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(languagesValLabel)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(encodingsLabel)
.addComponent(keywordSearchEncodings))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(ocrCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(ocrOnlyCheckbox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(limitedOcrCheckbox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap())
);
solrCheckbox.setSelected(true);
solrCheckbox.setText(org.openide.util.NbBundle.getMessage(KeywordSearchJobSettingsPanel.class, "KeywordSearchJobSettingsPanel.solrCheckbox.text")); // NOI18N
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 8;
gridBagConstraints.gridwidth = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints.insets = new java.awt.Insets(2, 10, 0, 0);
add(solrCheckbox, gridBagConstraints);
}// </editor-fold>//GEN-END:initComponents
private void ocrCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_ocrCheckBoxActionPerformed
@ -396,6 +432,7 @@ public final class KeywordSearchJobSettingsPanel extends IngestModuleIngestJobSe
private javax.swing.JTable listsTable;
private javax.swing.JCheckBox ocrCheckBox;
private javax.swing.JCheckBox ocrOnlyCheckbox;
private javax.swing.JCheckBox solrCheckbox;
private javax.swing.JLabel titleLabel;
// End of variables declaration//GEN-END:variables
}

View File

@ -130,7 +130,12 @@ public class KeywordSearchModuleFactory implements IngestModuleFactory {
@Override
public DataArtifactIngestModule createDataArtifactIngestModule(IngestModuleIngestJobSettings settings) {
return new KwsDataArtifactIngestModule();
if (!(settings instanceof KeywordSearchJobSettings)) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
"KeywordSearchModuleFactory.createFileIngestModule.exception.msg"));
}
return new KwsDataArtifactIngestModule((KeywordSearchJobSettings) settings);
}
@Override
@ -140,7 +145,12 @@ public class KeywordSearchModuleFactory implements IngestModuleFactory {
@Override
public AnalysisResultIngestModule createAnalysisResultIngestModule(IngestModuleIngestJobSettings settings) {
return new KwsAnalysisResultIngestModule();
if (!(settings instanceof KeywordSearchJobSettings)) {
throw new IllegalArgumentException(NbBundle.getMessage(this.getClass(),
"KeywordSearchModuleFactory.createFileIngestModule.exception.msg"));
}
return new KwsAnalysisResultIngestModule((KeywordSearchJobSettings) settings);
}
}

View File

@ -29,7 +29,6 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings;
import org.sleuthkit.autopsy.coreutils.StringExtract;
import org.sleuthkit.autopsy.coreutils.StringExtract.StringExtractUnicodeTable.SCRIPT;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.StringsExtractOptions;
import org.sleuthkit.autopsy.keywordsearch.KeywordSearchIngestModule.UpdateFrequency;
//This file contains constants and settings for KeywordSearch
class KeywordSearchSettings {
@ -46,34 +45,9 @@ class KeywordSearchSettings {
static final boolean LIMITED_OCR_ENABLED_DEFAULT = false;
private static boolean skipKnown = true;
private static final Logger logger = Logger.getLogger(KeywordSearchSettings.class.getName());
private static UpdateFrequency UpdateFreq = UpdateFrequency.DEFAULT;
private static List<StringExtract.StringExtractUnicodeTable.SCRIPT> stringExtractScripts = new ArrayList<>();
private static Map<String, String> stringExtractOptions = new HashMap<>();
/**
* Gets the update Frequency from KeywordSearch_Options.properties
*
* @return KeywordSearchIngestModule's update frequency
*/
static UpdateFrequency getUpdateFrequency() {
if (ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency") != null) { //NON-NLS
return UpdateFrequency.valueOf(ModuleSettings.getConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency")); //NON-NLS
}
//if it failed, return the default/last known value
logger.log(Level.WARNING, "Could not read property for UpdateFrequency, returning backup value."); //NON-NLS
return UpdateFrequency.DEFAULT;
}
/**
* Sets the update frequency and writes to KeywordSearch_Options.properties
*
* @param freq Sets KeywordSearchIngestModule to this value.
*/
static void setUpdateFrequency(UpdateFrequency freq) {
ModuleSettings.setConfigSetting(PROPERTIES_OPTIONS, "UpdateFrequency", freq.name()); //NON-NLS
UpdateFreq = freq;
}
/**
* Sets whether or not to skip adding known good files to the search during
* index.
@ -243,11 +217,6 @@ class KeywordSearchSettings {
logger.log(Level.INFO, "No configuration for NSRL found, generating default..."); //NON-NLS
KeywordSearchSettings.setSkipKnown(true);
}
//setting default Update Frequency
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, "UpdateFrequency")) { //NON-NLS
logger.log(Level.INFO, "No configuration for Update Frequency found, generating default..."); //NON-NLS
KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.DEFAULT);
}
//setting default Extract UTF8
if (!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, StringsExtractOptions.EXTRACT_UTF8.toString())) {
logger.log(Level.INFO, "No configuration for UTF8 found, generating default..."); //NON-NLS

View File

@ -20,11 +20,22 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.awt.Component;
import java.io.File;
import java.io.Reader;
import java.util.regex.Matcher;
import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JOptionPane;
import org.openide.util.Lookup;
import org.openide.windows.WindowManager;
import org.sleuthkit.autopsy.textextractors.TextExtractor;
import org.sleuthkit.autopsy.textextractors.TextExtractorFactory;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
class KeywordSearchUtil {
private static final String SNIPPET_DELIMITER = String.valueOf(Character.toChars(171));
public enum DIALOG_MESSAGE_TYPE {
@ -142,6 +153,36 @@ class KeywordSearchUtil {
}
return query;
}
/**
* Make a snippet from the given content that has the given hit plus some
* surrounding context.
*
* @param content The content to extract the snippet from.
*
* @param hitMatcher The Matcher that has the start/end info for where the
* hit is in the content.
* @param hit The actual hit in the content.
*
* @return A snippet extracted from content that contains hit plus some
* surrounding context.
*/
static String makeSnippet(String content, Matcher hitMatcher, String hit) {
// Get the snippet from the document.
final int end = hitMatcher.end();
final int start = hitMatcher.start();
return makeSnippet(content, start, end, hit);
}
static String makeSnippet(String content, int startOffset, int endOffset, String hit) {
// Get the snippet from the document.
int maxIndex = content.length() - 1;
return content.substring(Integer.max(0, startOffset - 20), Integer.max(0, startOffset))
+ SNIPPET_DELIMITER + hit + SNIPPET_DELIMITER
+ content.substring(Integer.min(maxIndex, endOffset), Integer.min(maxIndex, endOffset + 20));
}
/**
* Is the Keyword Search list at absPath an XML list?
@ -154,4 +195,40 @@ class KeywordSearchUtil {
//TODO: make this more robust, if necessary
return new File(absPath).getName().endsWith(".xml"); //NON-NLS
}
static Reader getReader(Content content) throws TextExtractorFactory.NoTextExtractorFound, TextExtractor.InitReaderException{
return getReader(content, null);
}
static Reader getReader(Content content, Lookup stringsExtractionContext) throws TextExtractorFactory.NoTextExtractorFound, TextExtractor.InitReaderException{
Reader reader = null;
if (content instanceof BlackboardArtifact) {
BlackboardArtifact artifact = (BlackboardArtifact) content;
if (artifact.getArtifactID() > 0) {
/*
* Artifact indexing is only supported for artifacts that use
* negative artifact ids to avoid overlapping with the object
* ids of other types of Content.
*/
return null;
}
TextExtractor blackboardExtractor = TextExtractorFactory.getExtractor(content, null);
reader = blackboardExtractor.getReader();
} else if (content instanceof AbstractFile) {
TextExtractor stringsExtractor = TextExtractorFactory.getStringsExtractor( content, stringsExtractionContext);
reader = stringsExtractor.getReader();
} else {
try {
TextExtractor contentExtractor = TextExtractorFactory.getExtractor(content, null);
reader = contentExtractor.getReader();
} catch (TextExtractorFactory.NoTextExtractorFound | TextExtractor.InitReaderException ex) {
// Try the StringsTextExtractor if Tika extractions fails.
TextExtractor stringsExtractor = TextExtractorFactory.getStringsExtractor(content, null);
reader = stringsExtractor.getReader();
}
}
return reader;
}
}

View File

@ -18,16 +18,14 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.io.Reader;
import java.util.logging.Level;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.AnalysisResultIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.ingest.IngestModule;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.datamodel.AnalysisResult;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.TskCoreException;
/**
* An analysis result ingest module that indexes text for keyword search. All
@ -40,21 +38,33 @@ public class KwsAnalysisResultIngestModule implements AnalysisResultIngestModule
private static final Logger LOGGER = Logger.getLogger(KeywordSearchIngestModule.class.getName());
private static final int TSK_KEYWORD_HIT_TYPE_ID = BlackboardArtifact.Type.TSK_KEYWORD_HIT.getTypeID();
private IngestJobContext context;
private KeywordSearchService searchService;
private final KeywordSearchJobSettings settings;
KwsAnalysisResultIngestModule(KeywordSearchJobSettings settings) {
this.settings = settings;
}
@Override
public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException {
this.context = context;
searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
}
@Override
public IngestModule.ProcessResult process(AnalysisResult result) {
try {
if (result.getType().getTypeID() != TSK_KEYWORD_HIT_TYPE_ID) {
searchService.index(result);
Ingester ingester = Ingester.getDefault();
Reader blackboardExtractedTextReader = KeywordSearchUtil.getReader(result);
String sourceName = result.getDisplayName() + "_" + result.getArtifactID();
ingester.indexMetaDataOnly(result, sourceName);
ingester.search(blackboardExtractedTextReader,
result.getArtifactID(),
sourceName, result,
context, true,
settings.isIndexToSolrEnabled(),
settings.getNamesOfEnabledKeyWordLists());
}
} catch (TskCoreException ex) {
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, String.format("Error indexing analysis result '%s' (job ID=%d)", result, context.getJobId()), ex); //NON-NLS
return IngestModule.ProcessResult.ERROR;
}

View File

@ -18,12 +18,13 @@
*/
package org.sleuthkit.autopsy.keywordsearch;
import java.io.Reader;
import java.util.logging.Level;
import org.openide.util.Lookup;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.ingest.DataArtifactIngestModule;
import org.sleuthkit.autopsy.ingest.IngestJobContext;
import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService;
import org.sleuthkit.autopsy.textextractors.TextExtractor;
import org.sleuthkit.autopsy.textextractors.TextExtractorFactory;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.DataArtifact;
import org.sleuthkit.datamodel.TskCoreException;
@ -39,24 +40,36 @@ public class KwsDataArtifactIngestModule implements DataArtifactIngestModule {
private static final Logger LOGGER = Logger.getLogger(KeywordSearchIngestModule.class.getName());
private static final int TSK_ASSOCIATED_OBJECT_TYPE_ID = BlackboardArtifact.Type.TSK_ASSOCIATED_OBJECT.getTypeID();
private IngestJobContext context;
private KeywordSearchService searchService;
private final KeywordSearchJobSettings settings;
KwsDataArtifactIngestModule(KeywordSearchJobSettings settings) {
this.settings = settings;
}
@Override
public void startUp(IngestJobContext context) throws IngestModuleException {
this.context = context;
searchService = Lookup.getDefault().lookup(KeywordSearchService.class);
}
@Override
public ProcessResult process(DataArtifact artifact) {
try {
if (artifact.getType().getTypeID() != TSK_ASSOCIATED_OBJECT_TYPE_ID) {
searchService.index(artifact);
Ingester ingester = Ingester.getDefault();
Reader blackboardExtractedTextReader = KeywordSearchUtil.getReader(artifact);
String sourceName = artifact.getDisplayName() + "_" + artifact.getArtifactID();
ingester.indexMetaDataOnly(artifact, sourceName);
ingester.search(blackboardExtractedTextReader,
artifact.getArtifactID(),
sourceName, artifact,
context, true,
settings.isIndexToSolrEnabled(),
settings.getNamesOfEnabledKeyWordLists());
}
} catch (TskCoreException ex) {
} catch (Exception ex) {
LOGGER.log(Level.SEVERE, String.format("Error indexing data artifact '%s' (job ID=%d)", artifact, context.getJobId()), ex); //NON-NLS
return ProcessResult.ERROR;
}
}
return ProcessResult.OK;
}

View File

@ -234,24 +234,28 @@ class LuceneQuery implements KeywordSearchQuery {
*/
@Override
public BlackboardArtifact createKeywordHitArtifact(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName, Long ingestJobId) {
return createKeywordHitArtifact(content, originalKeyword, foundKeyword, hit, snippet, listName, ingestJobId);
}
public static BlackboardArtifact createKeywordHitArtifact(Content content, Keyword originalKW, Keyword foundKeyword, KeywordHit hit, String snippet, String listName, Long ingestJobId) {
final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
Collection<BlackboardAttribute> attributes = new ArrayList<>();
if (snippet != null) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_PREVIEW, MODULE_NAME, snippet));
}
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm()));
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm().toLowerCase()));
if (StringUtils.isNotBlank(listName)) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, listName));
}
if (originalKeyword != null) {
BlackboardAttribute.ATTRIBUTE_TYPE selType = originalKeyword.getArtifactAttributeType();
if (originalKW != null) {
BlackboardAttribute.ATTRIBUTE_TYPE selType = originalKW.getArtifactAttributeType();
if (selType != null) {
attributes.add(new BlackboardAttribute(selType, MODULE_NAME, foundKeyword.getSearchTerm()));
}
if (originalKeyword.searchTermIsWholeWord()) {
if (originalKW.searchTermIsWholeWord()) {
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.LITERAL.ordinal()));
} else {
attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.SUBSTRING.ordinal()));

View File

@ -46,7 +46,6 @@ import org.sleuthkit.autopsy.datamodel.CreditCards;
import static org.sleuthkit.autopsy.keywordsearch.KeywordSearchSettings.MODULE_NAME;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.Account;
import org.sleuthkit.datamodel.AccountFileInstance;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
@ -431,7 +430,7 @@ final class RegexQuery implements KeywordSearchQuery {
keywordsFoundInThisDocument.put(hit, hit);
if (artifactAttributeType == null) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
hits.add(new KeywordHit(docId, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit));
} else {
switch (artifactAttributeType) {
case TSK_EMAIL:
@ -442,7 +441,7 @@ final class RegexQuery implements KeywordSearchQuery {
*/
if (hit.length() >= MIN_EMAIL_ADDR_LENGTH
&& DomainValidator.getInstance(true).isValidTld(hit.substring(hit.lastIndexOf('.')))) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
hits.add(new KeywordHit(docId, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit));
}
break;
@ -459,14 +458,14 @@ final class RegexQuery implements KeywordSearchQuery {
if (ccnMatcher.find()) {
final String group = ccnMatcher.group("ccn");
if (CreditCardValidator.isValidCCN(group)) {
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
hits.add(new KeywordHit(docId, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit));
}
}
}
break;
default:
hits.add(new KeywordHit(docId, makeSnippet(content, hitMatcher, hit), hit));
hits.add(new KeywordHit(docId, KeywordSearchUtil.makeSnippet(content, hitMatcher, hit), hit));
break;
}
}
@ -486,30 +485,6 @@ final class RegexQuery implements KeywordSearchQuery {
return hits;
}
/**
* Make a snippet from the given content that has the given hit plus some
* surrounding context.
*
* @param content The content to extract the snippet from.
*
* @param hitMatcher The Matcher that has the start/end info for where the
* hit is in the content.
* @param hit The actual hit in the content.
*
* @return A snippet extracted from content that contains hit plus some
* surrounding context.
*/
private String makeSnippet(String content, Matcher hitMatcher, String hit) {
// Get the snippet from the document.
int maxIndex = content.length() - 1;
final int end = hitMatcher.end();
final int start = hitMatcher.start();
return content.substring(Integer.max(0, start - 20), Integer.max(0, start))
+ SNIPPET_DELIMITER + hit + SNIPPET_DELIMITER
+ content.substring(Integer.min(maxIndex, end), Integer.min(maxIndex, end + 20));
}
@Override
public void addFilter(KeywordQueryFilter filter) {
this.filters.add(filter);
@ -573,6 +548,11 @@ final class RegexQuery implements KeywordSearchQuery {
*/
@Override
public BlackboardArtifact createKeywordHitArtifact(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName, Long ingestJobId) {
return createKeywordHitArtifact(content, originalKeyword, foundKeyword, hit, snippet, listName, ingestJobId);
}
public static BlackboardArtifact createKeywordHitArtifact(Content content, Keyword originalKW, Keyword foundKeyword, KeywordHit hit, String snippet, String listName, Long ingestJobId) {
final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
if (content == null) {
@ -583,8 +563,8 @@ final class RegexQuery implements KeywordSearchQuery {
/*
* Credit Card number hits are handled differently
*/
if (originalKeyword.getArtifactAttributeType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
createCCNAccount(content, foundKeyword, hit, snippet, listName, ingestJobId);
if (originalKW.getArtifactAttributeType() == ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
createCCNAccount(content, originalKW, foundKeyword, hit, snippet, listName, ingestJobId);
return null;
}
@ -594,8 +574,10 @@ final class RegexQuery implements KeywordSearchQuery {
*/
Collection<BlackboardAttribute> attributes = new ArrayList<>();
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm()));
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, MODULE_NAME, getQueryString()));
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD, MODULE_NAME, foundKeyword.getSearchTerm().toLowerCase()));
if(!originalKW.searchTermIsWholeWord() || !originalKW.searchTermIsLiteral()) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP, MODULE_NAME, originalKW.getSearchTerm()));
}
if (StringUtils.isNotBlank(listName)) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SET_NAME, MODULE_NAME, listName));
@ -608,7 +590,7 @@ final class RegexQuery implements KeywordSearchQuery {
-> attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT, MODULE_NAME, artifactID))
);
if (originalKeyword.searchTermIsLiteral()) {
if (originalKW.searchTermIsLiteral()) {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.SUBSTRING.ordinal()));
} else {
attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_SEARCH_TYPE, MODULE_NAME, KeywordSearch.QueryType.REGEX.ordinal()));
@ -625,11 +607,11 @@ final class RegexQuery implements KeywordSearchQuery {
}
}
private void createCCNAccount(Content content, Keyword foundKeyword, KeywordHit hit, String snippet, String listName, Long ingestJobId) {
private static void createCCNAccount(Content content, Keyword originalKW, Keyword foundKeyword, KeywordHit hit, String snippet, String listName, Long ingestJobId) {
final String MODULE_NAME = KeywordSearchModuleFactory.getModuleName();
if (originalKeyword.getArtifactAttributeType() != ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
if (originalKW.getArtifactAttributeType() != ATTRIBUTE_TYPE.TSK_CARD_NUMBER) {
LOGGER.log(Level.SEVERE, "Keyword hit is not a credit card number"); //NON-NLS
return;
}

View File

@ -583,7 +583,7 @@ public class Server {
List<Long> pids = new ArrayList<>();
//NOTE: these needs to be in sync with process start string in start()
final String pidsQuery = "Args.*.eq=-DSTOP.KEY=" + KEY + ",Args.*.eq=start.jar"; //NON-NLS
final String pidsQuery = "-DSTOP.KEY=" + KEY + "%start.jar"; //NON-NLS
long[] pidsArr = PlatformUtil.getJavaPIDs(pidsQuery);
if (pidsArr != null) {
@ -2513,11 +2513,29 @@ public class Server {
* @throws SolrServerException
*/
private int queryNumFileChunks(long contentID) throws SolrServerException, IOException {
String id = KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
final SolrQuery q
= new SolrQuery(Server.Schema.ID + ":" + id + Server.CHUNK_ID_SEPARATOR + "*");
q.setRows(0);
return (int) query(q).getResults().getNumFound();
final SolrQuery q = new SolrQuery();
q.setQuery("*:*");
String filterQuery = Schema.ID.toString() + ":" + KeywordSearchUtil.escapeLuceneQuery(Long.toString(contentID));
q.addFilterQuery(filterQuery);
q.setFields(Schema.NUM_CHUNKS.toString());
try {
SolrDocumentList solrDocuments = query(q).getResults();
if (!solrDocuments.isEmpty()) {
SolrDocument solrDocument = solrDocuments.get(0);
if (solrDocument != null) {
Object fieldValue = solrDocument.getFieldValue(Schema.NUM_CHUNKS.toString());
return (Integer)fieldValue;
}
}
} catch (Exception ex) {
// intentional "catch all" as Solr is known to throw all kinds of Runtime exceptions
logger.log(Level.SEVERE, "Error getting content from Solr. Solr document id " + contentID + ", query: " + filterQuery, ex); //NON-NLS
return 0;
}
// ERROR: we should never get here
logger.log(Level.SEVERE, "Error getting content from Solr. Solr document id " + contentID + ", query: " + filterQuery); //NON-NLS
return 0;
}
}

View File

@ -93,28 +93,22 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
return;
}
try {
TextExtractor blackboardExtractor = TextExtractorFactory.getExtractor(content, null);
Reader blackboardExtractedTextReader = blackboardExtractor.getReader();
Reader blackboardExtractedTextReader = KeywordSearchUtil.getReader(content);
String sourceName = artifact.getDisplayName() + "_" + artifact.getArtifactID();
ingester.indexMetaDataOnly(artifact, sourceName);
ingester.indexText(blackboardExtractedTextReader, artifact.getArtifactID(), sourceName, content, null);
} catch (Ingester.IngesterException | TextExtractorFactory.NoTextExtractorFound | TextExtractor.InitReaderException ex) {
// Will not cause an inline search becauce the keyword list is null
ingester.search(blackboardExtractedTextReader, artifact.getArtifactID(), sourceName, content, null, true, true, null);
} catch (Exception ex) {
throw new TskCoreException("Error indexing artifact", ex);
}
} else {
try {
TextExtractor contentExtractor = TextExtractorFactory.getExtractor(content, null);
Reader contentExtractedTextReader = contentExtractor.getReader();
ingester.indexText(contentExtractedTextReader, content.getId(), content.getName(), content, null);
} catch (TextExtractorFactory.NoTextExtractorFound | Ingester.IngesterException | TextExtractor.InitReaderException ex) {
try {
// Try the StringsTextExtractor if Tika extractions fails.
TextExtractor stringsExtractor = TextExtractorFactory.getStringsExtractor(content, null);
Reader stringsExtractedTextReader = stringsExtractor.getReader();
ingester.indexStrings(stringsExtractedTextReader, content.getId(), content.getName(), content, null);
} catch (Ingester.IngesterException | TextExtractor.InitReaderException ex1) {
throw new TskCoreException("Error indexing content", ex1);
}
Reader reader = KeywordSearchUtil.getReader(content);
// Will not cause an inline search becauce the keyword list is null
ingester.search(reader, content.getId(), content.getName(), content, null, true, true, null);
} catch (Exception ex) {
throw new TskCoreException("Error indexing content", ex);
}
// only do a Solr commit if ingest is not running. If ingest is running, the changes will
// be committed via a periodic commit or via final commit after the ingest job has finished.
@ -421,11 +415,11 @@ public class SolrSearchService implements KeywordSearchService, AutopsyService {
try {
String sourceName = artifact.getDisplayName() + "_" + artifact.getArtifactID();
TextExtractor blackboardExtractor = TextExtractorFactory.getExtractor((Content) artifact, null);
TextExtractor blackboardExtractor = TextExtractorFactory.getExtractor(artifact, null);
Reader blackboardExtractedTextReader = blackboardExtractor.getReader();
ingester.indexMetaDataOnly(artifact, sourceName);
ingester.indexText(blackboardExtractedTextReader, artifact.getId(), sourceName, artifact, null);
} catch (Ingester.IngesterException | TextExtractorFactory.NoTextExtractorFound | TextExtractor.InitReaderException ex) {
ingester.search(blackboardExtractedTextReader, artifact.getId(), sourceName, artifact, null, true, true, null);
} catch (Exception ex) {
throw new TskCoreException(ex.getCause().getMessage(), ex);
}
}

View File

@ -42,11 +42,11 @@ EMBEDDED SOFTWARE
This section lists the software components and libraries that are used by
Autopsy. These tools are bundled with the Windows installer, unless specified otherwise.
JRE (Java Runtime Environment) 1.8
- Web page: http://www.oracle.com/technetwork/java/index.html
- License: http://www.oracle.com/technetwork/java/javase/terms/license/index.html
JRE (Java Runtime Environment) 17
- Web page: https://bell-sw.com/pages/downloads/
- License: https://bell-sw.com/liberica_eula/
Netbeans 11.3 RCP platform and .jar files bundled with the platform
Netbeans 15 RCP platform and .jar files bundled with the platform
- Web page: https://netbeans.apache.org/
- License: https://www.apache.org/licenses/LICENSE-2.0

View File

@ -1,6 +1,6 @@
javac.source=17
file.reference.Rejistry-1.1-SNAPSHOT.jar=release/modules/ext/Rejistry-1.1-SNAPSHOT.jar
file.reference.sqlite-jdbc-3.36.0.3.jar=release/modules/ext/sqlite-jdbc-3.36.0.3.jar
javac.source=1.8
file.reference.sqlite-jdbc-3.42.0.0.jar=release/modules/ext/sqlite-jdbc-3.42.0.0.jar
javac.compilerargs=-Xlint -Xlint:-serial
license.file=../LICENSE-2.0.txt
nbm.homepage=http://www.sleuthkit.org/autopsy/

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