mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-15 01:07:42 +00:00
Merge branch 'develop' into 6267_null_exif_geodata
This commit is contained in:
commit
3ddab0ae57
@ -72,6 +72,9 @@
|
||||
<copy file="${thirdparty.dir}/sevenzip/sevenzipjbinding.jar" todir="${ext.dir}" />
|
||||
<copy file="${thirdparty.dir}/sevenzip/sevenzipjbinding-AllPlatforms.jar" todir="${ext.dir}" />
|
||||
<copy file="${thirdparty.dir}/stix/StixLib.jar" todir="${ext.dir}" />
|
||||
<copy todir="${ext.dir}">
|
||||
<fileset dir="${thirdparty.dir}/IcePDF 6.2.2/"/>
|
||||
</copy>
|
||||
<copy file="${thirdparty.dir}/jdom/jdom-2.0.5.jar" todir="${ext.dir}" />
|
||||
<copy file="${thirdparty.dir}/jdom/jdom-2.0.5-contrib.jar" todir="${ext.dir}" />
|
||||
<copy file="${thirdparty.dir}/DatCon/3.6.9/DatCon.jar" todir="${ext.dir}" />
|
||||
|
@ -2,8 +2,15 @@ file.reference.activemq-all-5.11.1.jar=release/modules/ext/activemq-all-5.11.1.j
|
||||
file.reference.apache-mime4j-core-0.8.2.jar=release\\modules\\ext\\apache-mime4j-core-0.8.2.jar
|
||||
file.reference.apache-mime4j-dom-0.8.2.jar=release\\modules\\ext\\apache-mime4j-dom-0.8.2.jar
|
||||
file.reference.asm-7.0.jar=release\\modules\\ext\\asm-7.0.jar
|
||||
file.reference.batik-awt-util-1.6.jar=release/modules/ext/batik-awt-util-1.6.jar
|
||||
file.reference.batik-dom-1.6.jar=release/modules/ext/batik-dom-1.6.jar
|
||||
file.reference.batik-svg-dom-1.6.jar=release/modules/ext/batik-svg-dom-1.6.jar
|
||||
file.reference.batik-svggen-1.6.jar=release/modules/ext/batik-svggen-1.6.jar
|
||||
file.reference.batik-util-1.6.jar=release/modules/ext/batik-util-1.6.jar
|
||||
file.reference.batik-xml-1.6.jar=release/modules/ext/batik-xml-1.6.jar
|
||||
file.reference.bcmail-jdk15on-1.60.jar=release\\modules\\ext\\bcmail-jdk15on-1.60.jar
|
||||
file.reference.bcpkix-jdk15on-1.60.jar=release\\modules\\ext\\bcpkix-jdk15on-1.60.jar
|
||||
file.reference.bcprov-ext-jdk15on-1.54.jar=release/modules/ext/bcprov-ext-jdk15on-1.54.jar
|
||||
file.reference.bcprov-jdk15on-1.60.jar=release\\modules\\ext\\bcprov-jdk15on-1.60.jar
|
||||
file.reference.boilerpipe-1.1.0.jar=release\\modules\\ext\\boilerpipe-1.1.0.jar
|
||||
file.reference.c3p0-0.9.5.jar=release/modules/ext/c3p0-0.9.5.jar
|
||||
@ -17,14 +24,17 @@ file.reference.commons-io-2.6.jar=release\\modules\\ext\\commons-io-2.6.jar
|
||||
file.reference.commons-lang3-3.8.1.jar=release\\modules\\ext\\commons-lang3-3.8.1.jar
|
||||
file.reference.commons-pool2-2.4.2.jar=release/modules/ext/commons-pool2-2.4.2.jar
|
||||
file.reference.cxf-rt-rs-client-3.3.0.jar=release\\modules\\ext\\cxf-rt-rs-client-3.3.0.jar
|
||||
file.reference.DatCon.jar=release/modules/ext/DatCon.jar
|
||||
file.reference.dec-0.1.2.jar=release\\modules\\ext\\dec-0.1.2.jar
|
||||
file.reference.decodetect-core-0.3.jar=release\\modules\\ext\\decodetect-core-0.3.jar
|
||||
file.reference.decodetect-core-0.3.jar=release/modules/ext/decodetect-core-0.3.jar
|
||||
file.reference.fontbox-2.0.13.jar=release\\modules\\ext\\fontbox-2.0.13.jar
|
||||
file.reference.geoapi-3.0.1.jar=release\\modules\\ext\\geoapi-3.0.1.jar
|
||||
file.reference.grib-4.5.5.jar=release\\modules\\ext\\grib-4.5.5.jar
|
||||
file.reference.httpclient-4.5.6.jar=release\\modules\\ext\\httpclient-4.5.6.jar
|
||||
file.reference.httpmime-4.5.6.jar=release\\modules\\ext\\httpmime-4.5.6.jar
|
||||
file.reference.httpservices-4.5.5.jar=release\\modules\\ext\\httpservices-4.5.5.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.isoparser-1.1.22.jar=release\\modules\\ext\\isoparser-1.1.22.jar
|
||||
file.reference.jackcess-2.2.0.jar=release\\modules\\ext\\jackcess-2.2.0.jar
|
||||
file.reference.jackcess-encrypt-2.1.4.jar=release\\modules\\ext\\jackcess-encrypt-2.1.4.jar
|
||||
@ -32,6 +42,8 @@ file.reference.jackson-annotations-2.9.7.jar=release\\modules\\ext\\jackson-anno
|
||||
file.reference.jackson-core-2.9.7.jar=release\\modules\\ext\\jackson-core-2.9.7.jar
|
||||
file.reference.jackson-databind-2.9.7.jar=release\\modules\\ext\\jackson-databind-2.9.7.jar
|
||||
file.reference.jai-imageio-core-1.4.0.jar=release\\modules\\ext\\jai-imageio-core-1.4.0.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.java-libpst-0.8.1.jar=release\\modules\\ext\\java-libpst-0.8.1.jar
|
||||
file.reference.javax.activation-1.2.0.jar=release\\modules\\ext\\javax.activation-1.2.0.jar
|
||||
file.reference.javax.annotation-api-1.3.2.jar=release\\modules\\ext\\javax.annotation-api-1.3.2.jar
|
||||
@ -50,7 +62,7 @@ file.reference.jsoup-1.11.3.jar=release\\modules\\ext\\jsoup-1.11.3.jar
|
||||
file.reference.jul-to-slf4j-1.7.25.jar=release\\modules\\ext\\jul-to-slf4j-1.7.25.jar
|
||||
file.reference.juniversalchardet-1.0.3.jar=release\\modules\\ext\\juniversalchardet-1.0.3.jar
|
||||
file.reference.junrar-2.0.0.jar=release\\modules\\ext\\junrar-2.0.0.jar
|
||||
file.reference.jutf7-1.0.0.jar=release\\modules\\ext\\jutf7-1.0.0.jar
|
||||
file.reference.jutf7-1.0.0.jar=release/modules/ext/jutf7-1.0.0.jar
|
||||
file.reference.jxmapviewer2-2.4.jar=release/modules/ext/jxmapviewer2-2.4.jar
|
||||
file.reference.jython-standalone-2.7.0.jar=release/modules/ext/jython-standalone-2.7.0.jar
|
||||
file.reference.libphonenumber-3.5.jar=release/modules/ext/libphonenumber-3.5.jar
|
||||
|
@ -355,6 +355,14 @@
|
||||
<runtime-relative-path>ext/commons-lang3-3.8.1.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\commons-lang3-3.8.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/batik-xml-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/batik-xml-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jai_core-1.1.3.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jai_core-1.1.3.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/gax-grpc-1.44.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/gax-grpc-1.44.0.jar</binary-origin>
|
||||
@ -371,6 +379,10 @@
|
||||
<runtime-relative-path>ext/opencensus-api-0.19.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/opencensus-api-0.19.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/batik-svg-dom-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/batik-svg-dom-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/gax-httpjson-0.61.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/gax-httpjson-0.61.0.jar</binary-origin>
|
||||
@ -479,6 +491,10 @@
|
||||
<runtime-relative-path>ext/xmpcore-5.1.3.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/xmpcore-5.1.3.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/batik-util-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/batik-util-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/javax.activation-1.2.0.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\javax.activation-1.2.0.jar</binary-origin>
|
||||
@ -499,6 +515,10 @@
|
||||
<runtime-relative-path>ext/jgraphx-4.1.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jgraphx-4.1.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/DatCon.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/DatCon.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/java-libpst-0.8.1.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\java-libpst-0.8.1.jar</binary-origin>
|
||||
@ -535,10 +555,6 @@
|
||||
<runtime-relative-path>ext/google-http-client-1.29.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-http-client-1.29.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.9.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.9.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/bcpkix-jdk15on-1.60.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\bcpkix-jdk15on-1.60.jar</binary-origin>
|
||||
@ -551,6 +567,10 @@
|
||||
<runtime-relative-path>ext/slf4j-api-1.7.25.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\slf4j-api-1.7.25.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/bcprov-ext-jdk15on-1.54.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/bcprov-ext-jdk15on-1.54.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/google-cloud-core-1.70.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-cloud-core-1.70.0.jar</binary-origin>
|
||||
@ -619,6 +639,14 @@
|
||||
<runtime-relative-path>ext/commons-validator-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/commons-validator-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/sleuthkit-postgresql-4.9.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.9.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/decodetect-core-0.3.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/decodetect-core-0.3.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jbig2-imageio-3.0.2.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\jbig2-imageio-3.0.2.jar</binary-origin>
|
||||
@ -667,6 +695,10 @@
|
||||
<runtime-relative-path>ext/SparseBitSet-1.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/SparseBitSet-1.1.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/batik-svggen-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/batik-svggen-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/c3p0-0.9.5.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/c3p0-0.9.5.jar</binary-origin>
|
||||
@ -735,6 +767,10 @@
|
||||
<runtime-relative-path>ext/postgresql-9.4.1211.jre7.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/postgresql-9.4.1211.jre7.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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/httpclient-4.5.6.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\httpclient-4.5.6.jar</binary-origin>
|
||||
@ -747,6 +783,10 @@
|
||||
<runtime-relative-path>ext/fontbox-2.0.13.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\fontbox-2.0.13.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/icepdf-core-6.2.2.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/icepdf-core-6.2.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/activemq-all-5.11.1.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/activemq-all-5.11.1.jar</binary-origin>
|
||||
@ -763,6 +803,10 @@
|
||||
<runtime-relative-path>ext/dec-0.1.2.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\dec-0.1.2.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/batik-dom-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/batik-dom-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/google-http-client-jackson2-1.29.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-http-client-jackson2-1.29.0.jar</binary-origin>
|
||||
@ -779,6 +823,14 @@
|
||||
<runtime-relative-path>ext/sevenzipjbinding-AllPlatforms.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/sevenzipjbinding-AllPlatforms.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/jutf7-1.0.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/jutf7-1.0.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/batik-awt-util-1.6.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/batik-awt-util-1.6.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/google-api-services-translate-v2-rev20170525-1.27.0.jar</binary-origin>
|
||||
@ -787,6 +839,10 @@
|
||||
<runtime-relative-path>ext/webp-imageio-sejda-0.1.0.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/webp-imageio-sejda-0.1.0.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<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/bcmail-jdk15on-1.60.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\bcmail-jdk15on-1.60.jar</binary-origin>
|
||||
@ -795,18 +851,6 @@
|
||||
<runtime-relative-path>ext/vorbis-java-tika-0.8.jar</runtime-relative-path>
|
||||
<binary-origin>release\modules\ext\vorbis-java-tika-0.8.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/decodetect-core-0.3.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/decodetect-core-0.3.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>
|
||||
</class-path-extension>
|
||||
<class-path-extension>
|
||||
<runtime-relative-path>ext/DatCon.jar</runtime-relative-path>
|
||||
<binary-origin>release/modules/ext/DatCon.jar</binary-origin>
|
||||
</class-path-extension>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
||||
|
@ -48,7 +48,8 @@ final class AccountDeviceInstanceNode extends AbstractNode {
|
||||
this.account = accountDeviceInstanceKey.getAccountDeviceInstance().getAccount();
|
||||
setName(account.getTypeSpecificID());
|
||||
setDisplayName(getName());
|
||||
setIconBaseWithExtension(Utils.getIconFilePath(account.getAccountType()));
|
||||
String iconPath = Utils.getIconFilePath(account.getAccountType());
|
||||
this.setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
|
||||
}
|
||||
|
||||
AccountDeviceInstance getAccountDeviceInstance() {
|
||||
|
@ -32,7 +32,7 @@ import org.openide.util.NbBundle;
|
||||
final class PinAccountsAction extends AbstractCVTAction {
|
||||
|
||||
static private final ImageIcon ICON = ImageUtilities.loadImageIcon(
|
||||
"/org/sleuthkit/autopsy/communications/images/marker--plus.png", false);
|
||||
"org/sleuthkit/autopsy/communications/images/marker--plus.png", false);
|
||||
private static final String SINGULAR_TEXT = Bundle.PinAccountsAction_singularText();
|
||||
private static final String PLURAL_TEXT = Bundle.PinAccountsAction_pluralText();
|
||||
|
||||
|
@ -32,7 +32,7 @@ import org.openide.util.NbBundle;
|
||||
final class ResetAndPinAccountsAction extends AbstractCVTAction {
|
||||
|
||||
private static final ImageIcon ICON = ImageUtilities.loadImageIcon(
|
||||
"/org/sleuthkit/autopsy/communications/images/marker--pin.png", false);
|
||||
"org/sleuthkit/autopsy/communications/images/marker--pin.png", false);
|
||||
private static final String SINGULAR_TEXT = Bundle.ResetAndPinAccountsAction_singularText();
|
||||
private static final String PLURAL_TEXT = Bundle.ResetAndPinAccountsAction_pluralText();
|
||||
|
||||
|
@ -32,7 +32,7 @@ import org.openide.util.NbBundle;
|
||||
final class UnpinAccountsAction extends AbstractCVTAction {
|
||||
|
||||
static final private ImageIcon ICON = ImageUtilities.loadImageIcon(
|
||||
"/org/sleuthkit/autopsy/communications/images/marker--minus.png", false);
|
||||
"org/sleuthkit/autopsy/communications/images/marker--minus.png", false);
|
||||
private static final String SINGULAR_TEXT = Bundle.UnpinAccountsAction_singularText();
|
||||
private static final String PLURAL_TEXT = Bundle.UnpinAccountsAction_pluralText();
|
||||
|
||||
|
@ -112,6 +112,8 @@ MessageContentViewer.attachmentsPanel.TabConstraints.tabTitle=Attachments
|
||||
MessageContentViewer.viewInNewWindowButton.text=View in New Window
|
||||
JPEGViewerDummy.jLabel1.text=You are looking at a JPEG file:
|
||||
JPEGViewerDummy.jTextField1.text=jTextField1
|
||||
PDFViewer.encryptedDialog=This document is password protected.
|
||||
PDFViewer.errorDialog=An error occurred while opening this PDF document. Check the logs for more information. You may continue to use this feature on other PDF documents.
|
||||
PListNode.KeyCol=Key
|
||||
PListNode.TypeCol=Type
|
||||
PListNode.ValueCol=Value
|
||||
|
@ -50,7 +50,8 @@ public class FileViewer extends javax.swing.JPanel implements DataContentViewer
|
||||
new PListViewer(),
|
||||
new MediaFileViewer(),
|
||||
new HtmlViewer(),
|
||||
new WindowsRegistryViewer()
|
||||
new WindowsRegistryViewer(),
|
||||
new PDFViewer()
|
||||
};
|
||||
|
||||
private FileTypeViewer lastViewer;
|
||||
|
192
Core/src/org/sleuthkit/autopsy/contentviewers/PDFViewer.java
Executable file
192
Core/src/org/sleuthkit/autopsy/contentviewers/PDFViewer.java
Executable file
@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2020 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.contentviewers;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.logging.Level;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.SwingWorker;
|
||||
|
||||
import org.openide.util.NbBundle;
|
||||
|
||||
import org.sleuthkit.datamodel.AbstractFile;
|
||||
import org.sleuthkit.datamodel.ReadContentInputStream;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil;
|
||||
|
||||
import org.icepdf.core.exceptions.PDFException;
|
||||
import org.icepdf.core.exceptions.PDFSecurityException;
|
||||
import org.icepdf.core.pobjects.Document;
|
||||
|
||||
import org.icepdf.ri.common.ComponentKeyBinding;
|
||||
import org.icepdf.ri.common.SwingController;
|
||||
import org.icepdf.ri.common.SwingViewBuilder;
|
||||
import org.icepdf.ri.common.views.DocumentViewControllerImpl;
|
||||
import org.icepdf.ri.common.views.DocumentViewModelImpl;
|
||||
import org.icepdf.ri.util.PropertiesManager;
|
||||
|
||||
/**
|
||||
* Application content viewer for PDF files.
|
||||
*/
|
||||
public class PDFViewer implements FileTypeViewer {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(PDFViewer.class.getName());
|
||||
|
||||
private JPanel container;
|
||||
private final PropertiesManager propsManager;
|
||||
|
||||
public PDFViewer() {
|
||||
container = createNewContainer();
|
||||
propsManager = getCustomProperties();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getSupportedMIMETypes() {
|
||||
return Arrays.asList("application/pdf");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFile(AbstractFile file) {
|
||||
// The 'C' in IcePDFs MVC set up.
|
||||
SwingController controller = new SwingController();
|
||||
|
||||
// Builder for the 'V' in IcePDFs MVC set up
|
||||
SwingViewBuilder viewBuilder = new SwingViewBuilder(controller, propsManager);
|
||||
|
||||
// The 'V' in IcePDFs MVC set up.
|
||||
JPanel icePdfPanel = viewBuilder.buildViewerPanel();
|
||||
|
||||
// This connects keyboard commands performed on the view to the controller.
|
||||
// The only keyboard commands that the controller supports is Ctrl-C for
|
||||
// copying selected text.
|
||||
ComponentKeyBinding.install(controller, icePdfPanel);
|
||||
|
||||
// Ensure the preferredSize is in sync with the parent container.
|
||||
icePdfPanel.setPreferredSize(this.container.getPreferredSize());
|
||||
|
||||
// Add the IcePDF view to the center of our container.
|
||||
this.container.add(icePdfPanel, BorderLayout.CENTER);
|
||||
|
||||
// Document is the 'M' in IcePDFs MVC set up. Read the data needed to
|
||||
// populate the model in the background.
|
||||
new SwingWorker<Document, Void>() {
|
||||
@Override
|
||||
protected Document doInBackground() throws PDFException, PDFSecurityException, IOException {
|
||||
ReadContentInputStream stream = new ReadContentInputStream(file);
|
||||
Document doc = new Document();
|
||||
// This will read the stream into memory.
|
||||
doc.setInputStream(stream, null);
|
||||
return doc;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void done() {
|
||||
// Customize the view selection modes on the EDT. Each of these
|
||||
// will cause UI widgets to be updated.
|
||||
try {
|
||||
Document doc = get();
|
||||
controller.openDocument(doc, null);
|
||||
// This makes the PDF viewer appear as one continuous
|
||||
// document, which is the default for most popular PDF viewers.
|
||||
controller.setPageViewMode(DocumentViewControllerImpl.ONE_COLUMN_VIEW, true);
|
||||
// This makes it possible to select text by left clicking and dragging.
|
||||
controller.setDisplayTool(DocumentViewModelImpl.DISPLAY_TOOL_TEXT_SELECTION);
|
||||
} catch (InterruptedException ex) {
|
||||
// Do nothing.
|
||||
} catch (ExecutionException ex) {
|
||||
Throwable exCause = ex.getCause();
|
||||
if (exCause instanceof PDFSecurityException) {
|
||||
showEncryptionDialog();
|
||||
} else {
|
||||
logger.log(Level.WARNING, String.format("PDF content viewer "
|
||||
+ "was unable to open document with id %d and name %s",
|
||||
file.getId(), file.getName()), ex);
|
||||
showErrorDialog();
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getComponent() {
|
||||
return container;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetComponent() {
|
||||
container = createNewContainer();
|
||||
}
|
||||
|
||||
// The container should have a BorderLayout otherwise the IcePDF panel may
|
||||
// not be visible.
|
||||
private JPanel createNewContainer() {
|
||||
return new JPanel(new BorderLayout());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSupported(AbstractFile file) {
|
||||
return getSupportedMIMETypes().contains(file.getMIMEType());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets property values that will control how the view will be constructed
|
||||
* in IcePDFs MVC set up.
|
||||
*/
|
||||
private PropertiesManager getCustomProperties() {
|
||||
Properties props = new Properties();
|
||||
|
||||
// See link for available properties. https://www.icesoft.org/wiki/display/PDF/Customizing+the+Viewer
|
||||
props.setProperty(PropertiesManager.PROPERTY_SHOW_UTILITY_SAVE, "false");
|
||||
props.setProperty(PropertiesManager.PROPERTY_SHOW_UTILITY_OPEN, "false");
|
||||
props.setProperty(PropertiesManager.PROPERTY_SHOW_UTILITY_PRINT, "false");
|
||||
props.setProperty(PropertiesManager.PROPERTY_SHOW_TOOLBAR_ANNOTATION, "false");
|
||||
props.setProperty(PropertiesManager.PROPERTY_SHOW_UTILITYPANE_ANNOTATION, "false");
|
||||
|
||||
// This suppresses a pop-up, from IcePDF, that asks if you'd like to
|
||||
// save configuration changes to disk.
|
||||
props.setProperty("application.showLocalStorageDialogs", "false");
|
||||
|
||||
ResourceBundle defaultMessageBundle = ResourceBundle.getBundle(PropertiesManager.DEFAULT_MESSAGE_BUNDLE);
|
||||
return new PropertiesManager(System.getProperties(), props, defaultMessageBundle);
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"PDFViewer.errorDialog=An error occurred while opening this PDF document. "
|
||||
+ "Check the logs for more information. You may continue to use "
|
||||
+ "this feature on other PDF documents."
|
||||
})
|
||||
private void showErrorDialog() {
|
||||
MessageNotifyUtil.Message.error(Bundle.PDFViewer_errorDialog());
|
||||
}
|
||||
|
||||
@NbBundle.Messages({
|
||||
"PDFViewer.encryptedDialog=This document is password protected."
|
||||
})
|
||||
private void showEncryptionDialog() {
|
||||
MessageNotifyUtil.Message.error(Bundle.PDFViewer_encryptedDialog());
|
||||
}
|
||||
}
|
@ -260,7 +260,7 @@ public class BlackboardArtifactNode extends AbstractContentNode<BlackboardArtifa
|
||||
String displayName = srcContent.getName();
|
||||
setDisplayName(displayName);
|
||||
setShortDescription(displayName);
|
||||
setIconBaseWithExtension(iconPath);
|
||||
setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
|
||||
Case.addEventTypeSubscriber(CASE_EVENTS_OF_INTEREST, weakListener);
|
||||
}
|
||||
|
||||
|
@ -290,7 +290,8 @@ public class ExtractedContent implements AutopsyVisitableItem {
|
||||
super(Children.create(new ArtifactFactory(type), true), Lookups.singleton(type.getDisplayName()));
|
||||
super.setName(type.getTypeName());
|
||||
this.type = type;
|
||||
this.setIconBaseWithExtension(IconsUtil.getIconFilePath(type.getTypeID())); //NON-NLS
|
||||
String iconPath = IconsUtil.getIconFilePath(type.getTypeID());
|
||||
setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath);
|
||||
updateDisplayName();
|
||||
}
|
||||
|
||||
|
@ -33,8 +33,10 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -108,6 +110,9 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
private final RejectAccounts rejectActionInstance;
|
||||
private final ApproveAccounts approveActionInstance;
|
||||
|
||||
// tracks the number of each account type found
|
||||
private final AccountTypeResults accountTypeResults;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -129,6 +134,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
|
||||
this.rejectActionInstance = new RejectAccounts();
|
||||
this.approveActionInstance = new ApproveAccounts();
|
||||
this.accountTypeResults = new AccountTypeResults();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -250,6 +256,63 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracks the account types and the number of account types found.
|
||||
*/
|
||||
private class AccountTypeResults {
|
||||
private final Map<String, Long> counts = new HashMap<>();
|
||||
|
||||
AccountTypeResults() {
|
||||
update();
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the type name of the Account.Type, provides the count of those type.
|
||||
* @param accountType The type name of the Account.Type.
|
||||
* @return The number of results found for the given account type.
|
||||
*/
|
||||
Long getCount(String accountType) {
|
||||
return counts.get(accountType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves an alphabetically organized list of all the account types.
|
||||
* @return An alphabetically organized list of all the account types.
|
||||
*/
|
||||
List<String> getTypes() {
|
||||
List<String> types = new ArrayList<>(counts.keySet());
|
||||
Collections.sort(types);
|
||||
return types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Queries the database and updates the counts for each account type.
|
||||
*/
|
||||
private void update() {
|
||||
String accountTypesInUseQuery
|
||||
= "SELECT blackboard_attributes.value_text as account_type, COUNT(*) as count "
|
||||
+ " FROM blackboard_artifacts " //NON-NLS
|
||||
+ " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
|
||||
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS
|
||||
+ " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() //NON-NLS
|
||||
+ getFilterByDataSourceClause()
|
||||
+ " GROUP BY blackboard_attributes.value_text ";
|
||||
|
||||
try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
|
||||
ResultSet resultSet = executeQuery.getResultSet()) {
|
||||
|
||||
counts.clear();
|
||||
while (resultSet.next()) {
|
||||
String accountType = resultSet.getString("account_type");
|
||||
Long count = resultSet.getLong("count");
|
||||
counts.put(accountType, count);
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error querying for account_types", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates child nodes for each account type in the db.
|
||||
*/
|
||||
@ -281,6 +344,7 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
ModuleDataEvent eventData = (ModuleDataEvent) evt.getOldValue();
|
||||
if (null != eventData
|
||||
&& eventData.getBlackboardArtifactType().getTypeID() == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
|
||||
accountTypeResults.update();
|
||||
reviewStatusBus.post(eventData);
|
||||
}
|
||||
} catch (NoCurrentCaseException notUsed) {
|
||||
@ -324,37 +388,31 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
|
||||
@Override
|
||||
protected boolean createKeys(List<String> list) {
|
||||
String accountTypesInUseQuery
|
||||
= "SELECT DISTINCT blackboard_attributes.value_text as account_type "
|
||||
+ " FROM blackboard_artifacts " //NON-NLS
|
||||
+ " JOIN blackboard_attributes ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id " //NON-NLS
|
||||
+ " WHERE blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID() //NON-NLS
|
||||
+ " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID() //NON-NLS
|
||||
+ getFilterByDataSourceClause();
|
||||
|
||||
try (SleuthkitCase.CaseDbQuery executeQuery = skCase.executeQuery(accountTypesInUseQuery);
|
||||
ResultSet resultSet = executeQuery.getResultSet()) {
|
||||
while (resultSet.next()) {
|
||||
String accountType = resultSet.getString("account_type");
|
||||
list.add(accountType);
|
||||
}
|
||||
} catch (TskCoreException | SQLException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error querying for account_types", ex);
|
||||
}
|
||||
|
||||
list.addAll(accountTypeResults.getTypes());
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given node with the reviewStatusBus and returns
|
||||
* the node wrapped in an array.
|
||||
* @param node The node to be wrapped.
|
||||
* @return The array containing this node.
|
||||
*/
|
||||
private Node[] getNodeArr(Node node) {
|
||||
reviewStatusBus.register(node);
|
||||
return new Node[]{node};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Node[] createNodesForKey(String acountTypeName) {
|
||||
|
||||
if (Account.Type.CREDIT_CARD.getTypeName().equals(acountTypeName)) {
|
||||
return new Node[]{new CreditCardNumberAccountTypeNode()};
|
||||
return getNodeArr(new CreditCardNumberAccountTypeNode());
|
||||
} else {
|
||||
|
||||
try {
|
||||
Account.Type accountType = skCase.getCommunicationsManager().getAccountType(acountTypeName);
|
||||
return new Node[]{new DefaultAccountTypeNode(accountType)};
|
||||
return getNodeArr(new DefaultAccountTypeNode(accountType));
|
||||
} catch (TskCoreException ex) {
|
||||
LOGGER.log(Level.SEVERE, "Error getting display name for account type. ", ex);
|
||||
}
|
||||
@ -509,11 +567,14 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
* no special behavior.
|
||||
*/
|
||||
final public class DefaultAccountTypeNode extends DisplayableItemNode {
|
||||
private final Account.Type accountType;
|
||||
|
||||
private DefaultAccountTypeNode(Account.Type accountType) {
|
||||
super(Children.create(new DefaultAccountFactory(accountType), true), Lookups.singleton(accountType));
|
||||
setName(accountType.getDisplayName());
|
||||
this.setIconBaseWithExtension(getIconFilePath(accountType)); //NON-NLS
|
||||
this.accountType = accountType;
|
||||
String iconPath = getIconFilePath(accountType);
|
||||
this.setIconBaseWithExtension(iconPath != null && iconPath.charAt(0) == '/' ? iconPath.substring(1) : iconPath); //NON-NLS
|
||||
updateName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -530,6 +591,24 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
public String getItemType() {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
|
||||
@Subscribe
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
updateName();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
updateName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest counts for the account type and then updates the name.
|
||||
*/
|
||||
public void updateName() {
|
||||
setName(String.format("%s (%d)", accountType.getDisplayName(), accountTypeResults.getCount(accountType.getTypeName())));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -660,6 +739,23 @@ final public class Accounts implements AutopsyVisitableItem {
|
||||
this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/credit-cards.png"); //NON-NLS
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the latest counts for the account type and then updates the name.
|
||||
*/
|
||||
public void updateName() {
|
||||
setName(String.format("%s (%d)", Account.Type.CREDIT_CARD.getDisplayName(), accountTypeResults.getCount(Account.Type.CREDIT_CARD.getTypeName())));
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void handleReviewStatusChange(ReviewStatusChangeEvent event) {
|
||||
updateName();
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
void handleDataAdded(ModuleDataEvent event) {
|
||||
updateName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeafTypeNode() {
|
||||
return false;
|
||||
|
@ -34,8 +34,8 @@ final class DiscoveryUiUtils {
|
||||
private static final int ICON_SIZE = 16;
|
||||
private static final String RED_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/red-circle-exclamation.png";
|
||||
private static final String YELLOW_CIRCLE_ICON_PATH = "org/sleuthkit/autopsy/images/yellow-circle-yield.png";
|
||||
private static final String DELETE_ICON_PATH = "/org/sleuthkit/autopsy/images/file-icon-deleted.png";
|
||||
private static final String UNSUPPORTED_DOC_PATH = "/org/sleuthkit/autopsy/images/image-extraction-not-supported.png";
|
||||
private static final String DELETE_ICON_PATH = "org/sleuthkit/autopsy/images/file-icon-deleted.png";
|
||||
private static final String UNSUPPORTED_DOC_PATH = "org/sleuthkit/autopsy/images/image-extraction-not-supported.png";
|
||||
private static final ImageIcon INTERESTING_SCORE_ICON = new ImageIcon(ImageUtilities.loadImage(YELLOW_CIRCLE_ICON_PATH, false));
|
||||
private static final ImageIcon NOTABLE_SCORE_ICON = new ImageIcon(ImageUtilities.loadImage(RED_CIRCLE_ICON_PATH, false));
|
||||
private static final ImageIcon DELETED_ICON = new ImageIcon(ImageUtilities.loadImage(DELETE_ICON_PATH, false));
|
||||
|
@ -22,6 +22,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
import javafx.util.Pair;
|
||||
import org.sleuthkit.autopsy.casemodule.Case;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
|
||||
@ -75,11 +76,11 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
*
|
||||
* @param mapWaypoints List of filtered MapWaypoints.
|
||||
*/
|
||||
abstract void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints);
|
||||
abstract void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks);
|
||||
|
||||
@Override
|
||||
public void process(List<Waypoint> waypoints) {
|
||||
List<Track> tracks = null;
|
||||
List<Track> tracks = new ArrayList<>();
|
||||
if (filters.getArtifactTypes().contains(ARTIFACT_TYPE.TSK_GPS_TRACK)) {
|
||||
try {
|
||||
tracks = Track.getTracks(Case.getCurrentCase().getSleuthkitCase(), filters.getDataSources());
|
||||
@ -87,11 +88,15 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
logger.log(Level.WARNING, "Exception thrown while retrieving list of Tracks", ex);
|
||||
}
|
||||
}
|
||||
Pair<List<Waypoint>, List<List<Waypoint>>> waypointsAndTracks = createWaypointList(waypoints, tracks);
|
||||
|
||||
List<Waypoint> completeList = createWaypointList(waypoints, tracks);
|
||||
final Set<MapWaypoint> pointSet = MapWaypoint.getWaypoints(completeList);
|
||||
final Set<MapWaypoint> pointSet = MapWaypoint.getWaypoints(waypointsAndTracks.getKey());
|
||||
final List<Set<MapWaypoint>> trackSets = new ArrayList<>();
|
||||
for (List<Waypoint> t : waypointsAndTracks.getValue()) {
|
||||
trackSets.add(MapWaypoint.getWaypoints(t));
|
||||
}
|
||||
|
||||
handleFilteredWaypointSet(pointSet);
|
||||
handleFilteredWaypointSet(pointSet, trackSets);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -104,8 +109,9 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
* @return A list of waypoints including the tracks based on the current
|
||||
* filters.
|
||||
*/
|
||||
private List<Waypoint> createWaypointList(List<Waypoint> waypoints, List<Track> tracks) {
|
||||
private Pair<List<Waypoint>, List<List<Waypoint>>> createWaypointList(List<Waypoint> waypoints, List<Track> tracks) {
|
||||
final List<Waypoint> completeList = new ArrayList<>();
|
||||
List<List<Waypoint>> filteredTracks = new ArrayList<>();
|
||||
|
||||
if (tracks != null) {
|
||||
Long timeRangeEnd;
|
||||
@ -117,19 +123,22 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
timeRangeStart = timeRangeEnd - (86400 * filters.getMostRecentNumDays());
|
||||
|
||||
completeList.addAll(getWaypointsInRange(timeRangeStart, timeRangeEnd, waypoints));
|
||||
completeList.addAll(getTracksInRange(timeRangeStart, timeRangeEnd, tracks));
|
||||
|
||||
filteredTracks = getTracksInRange(timeRangeStart, timeRangeEnd, tracks);
|
||||
for (List<Waypoint> filteredTrack : filteredTracks) {
|
||||
completeList.addAll(filteredTrack);
|
||||
}
|
||||
} else {
|
||||
completeList.addAll(waypoints);
|
||||
for (Track track : tracks) {
|
||||
completeList.addAll(track.getPath());
|
||||
filteredTracks.add(track.getPath());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
completeList.addAll(waypoints);
|
||||
}
|
||||
|
||||
return completeList;
|
||||
return new Pair<>(completeList, filteredTracks);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -158,31 +167,30 @@ abstract class AbstractWaypointFetcher implements WaypointBuilder.WaypointFilter
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of waypoints from the given tracks that fall into for
|
||||
* tracks that fall into the given time range. The track start time will
|
||||
* used for determining if the whole track falls into the range.
|
||||
* Return a list of lists of waypoints from the given tracks that fall into
|
||||
* the given time range. The track start time will used for determining if
|
||||
* the whole track falls into the range.
|
||||
*
|
||||
* @param timeRangeStart start timestamp of range (seconds from java epoch)
|
||||
* @param timeRangeEnd start timestamp of range (seconds from java epoch)
|
||||
* @param tracks Track list.
|
||||
*
|
||||
* @return A list of waypoints that that belong to tracks that fall into the
|
||||
* time range.
|
||||
* @return A list of lists of waypoints corresponding to belong to tracks
|
||||
* that exist within the time range.
|
||||
*/
|
||||
private List<Waypoint> getTracksInRange(Long timeRangeStart, Long timeRangeEnd, List<Track> tracks) {
|
||||
List<Waypoint> completeList = new ArrayList<>();
|
||||
private List<List<Waypoint>> getTracksInRange(Long timeRangeStart, Long timeRangeEnd, List<Track> tracks) {
|
||||
List<List<Waypoint>> ret = new ArrayList<>();
|
||||
if (tracks != null) {
|
||||
for (Track track : tracks) {
|
||||
Long trackTime = track.getStartTime();
|
||||
|
||||
if ((trackTime == null && filters.showWaypointsWithoutTimeStamp())
|
||||
|| (trackTime != null && (trackTime >= timeRangeStart && trackTime <= timeRangeEnd))) {
|
||||
|
||||
completeList.addAll(track.getPath());
|
||||
ret.add(track.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
return completeList;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -330,7 +330,7 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
*
|
||||
* @param waypointList
|
||||
*/
|
||||
void addWaypointsToMap(Set<MapWaypoint> waypointList) {
|
||||
void addWaypointsToMap(Set<MapWaypoint> waypointList, List<Set<MapWaypoint>> tracks) {
|
||||
SwingUtilities.invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
@ -347,6 +347,8 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
}
|
||||
mapPanel.clearWaypoints();
|
||||
mapPanel.setWaypoints(waypointList);
|
||||
mapPanel.setTracks(tracks);
|
||||
mapPanel.initializePainter();
|
||||
setWaypointLoading(false);
|
||||
geoFilterPanel.setEnabled(true);
|
||||
}
|
||||
@ -499,8 +501,8 @@ public final class GeolocationTopComponent extends TopComponent {
|
||||
}
|
||||
|
||||
@Override
|
||||
void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints) {
|
||||
addWaypointsToMap(mapWaypoints);
|
||||
void handleFilteredWaypointSet(Set<MapWaypoint> mapWaypoints, List<Set<MapWaypoint>> tracks) {
|
||||
addWaypointsToMap(mapWaypoints, tracks);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,11 +19,13 @@
|
||||
package org.sleuthkit.autopsy.geolocation;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.RenderingHints;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.ComponentAdapter;
|
||||
@ -71,6 +73,9 @@ import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
|
||||
import org.sleuthkit.datamodel.TskCoreException;
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.SwingUtilities;
|
||||
import org.jxmapviewer.painter.CompoundPainter;
|
||||
import org.jxmapviewer.painter.Painter;
|
||||
import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
|
||||
|
||||
/**
|
||||
* The map panel. This panel contains the jxmapviewer MapViewer
|
||||
@ -84,6 +89,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
private boolean zoomChanging;
|
||||
private KdTree<MapWaypoint> waypointTree;
|
||||
private Set<MapWaypoint> waypointSet;
|
||||
private List<Set<MapWaypoint>> tracks = new ArrayList<>();
|
||||
|
||||
private Popup currentPopup;
|
||||
private final PopupFactory popupFactory;
|
||||
@ -96,6 +102,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
private BufferedImage transparentWaypointImage;
|
||||
|
||||
private MapWaypoint currentlySelectedWaypoint;
|
||||
private Set<MapWaypoint> currentlySelectedTrack;
|
||||
|
||||
/**
|
||||
* Creates new form MapPanel
|
||||
@ -204,6 +211,10 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
|
||||
mapViewer.setCenterPosition(new GeoPosition(0, 0));
|
||||
|
||||
initializePainter();
|
||||
}
|
||||
|
||||
void initializePainter() {
|
||||
// Basic painters for the way points.
|
||||
WaypointPainter<MapWaypoint> waypointPainter = new WaypointPainter<MapWaypoint>() {
|
||||
@Override
|
||||
@ -217,7 +228,12 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
};
|
||||
waypointPainter.setRenderer(new MapWaypointRenderer());
|
||||
|
||||
mapViewer.setOverlayPainter(waypointPainter);
|
||||
ArrayList<Painter<JXMapViewer>> painters = new ArrayList<>();
|
||||
painters.add(new MapTrackRenderer(tracks));
|
||||
painters.add(waypointPainter);
|
||||
|
||||
CompoundPainter<JXMapViewer> compoundPainter = new CompoundPainter<>(painters);
|
||||
mapViewer.setOverlayPainter(compoundPainter);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -306,6 +322,15 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
mapViewer.repaint();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the given List of tracks from which to draw paths later
|
||||
*
|
||||
* @param tracks
|
||||
*/
|
||||
void setTracks(List<Set<MapWaypoint>> tracks) {
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current zoom level.
|
||||
*
|
||||
@ -324,6 +349,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
void clearWaypoints() {
|
||||
waypointTree = null;
|
||||
currentlySelectedWaypoint = null;
|
||||
currentlySelectedTrack = null;
|
||||
if (currentPopup != null) {
|
||||
currentPopup.hide();
|
||||
}
|
||||
@ -661,9 +687,17 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
if (!evt.isPopupTrigger() && SwingUtilities.isLeftMouseButton(evt)) {
|
||||
List<MapWaypoint> waypoints = findClosestWaypoint(evt.getPoint());
|
||||
if (waypoints.size() > 0) {
|
||||
currentlySelectedWaypoint = waypoints.get(0);
|
||||
MapWaypoint selection = waypoints.get(0);
|
||||
currentlySelectedWaypoint = selection;
|
||||
for (Set<MapWaypoint> track : tracks) {
|
||||
if (track.contains(selection)) {
|
||||
currentlySelectedTrack = track;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentlySelectedWaypoint = null;
|
||||
currentlySelectedTrack = null;
|
||||
}
|
||||
showDetailsPopup();
|
||||
}
|
||||
@ -691,18 +725,18 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
*/
|
||||
private class MapWaypointRenderer implements WaypointRenderer<MapWaypoint> {
|
||||
|
||||
private final Map<Color, BufferedImage> imageCache = new HashMap<>();
|
||||
private final Map<Color, BufferedImage> dotImageCache = new HashMap<>();
|
||||
private final Map<Color, BufferedImage> waypointImageCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param waypoint the waypoint for which to get the color
|
||||
* @param currentlySelectedWaypoint the waypoint that is currently
|
||||
* selected
|
||||
* @param waypoint the waypoint for which to get the color selected
|
||||
* @return the color that this waypoint should be rendered
|
||||
*/
|
||||
private Color getColor(MapWaypoint waypoint, MapWaypoint currentlySelectedWaypoint) {
|
||||
private Color getColor(MapWaypoint waypoint) {
|
||||
Color baseColor = waypoint.getColor();
|
||||
if (waypoint.equals(currentlySelectedWaypoint)) {
|
||||
if (waypoint.equals(currentlySelectedWaypoint)
|
||||
|| (currentlySelectedTrack != null && currentlySelectedTrack.contains(waypoint))) {
|
||||
// Highlight this waypoint since it is selected
|
||||
return Color.YELLOW;
|
||||
} else {
|
||||
@ -710,10 +744,32 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dot image with the specified color
|
||||
*
|
||||
* @param color the color of the new image
|
||||
* @return the new dot image
|
||||
*/
|
||||
private BufferedImage createTrackDotImage(Color color) {
|
||||
int w = 10;
|
||||
int h = 10;
|
||||
|
||||
BufferedImage ret = new BufferedImage(w + 2, h + 2, BufferedImage.TYPE_INT_ARGB);
|
||||
Graphics2D g = ret.createGraphics();
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setColor(color);
|
||||
g.fillOval(1, 1, w, h);
|
||||
g.setColor(Color.BLACK);
|
||||
g.setStroke(new BasicStroke(1));
|
||||
g.drawOval(1, 1, w, h);
|
||||
g.dispose();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a waypoint image with the specified color
|
||||
*
|
||||
* @param color the color of the new waypoint image
|
||||
* @param color the color of the new image
|
||||
* @return the new waypoint image
|
||||
*/
|
||||
private BufferedImage createWaypointImage(Color color) {
|
||||
@ -723,6 +779,7 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
BufferedImage ret = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D g = ret.createGraphics();
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.drawImage(whiteWaypointImage, 0, 0, null);
|
||||
g.setComposite(AlphaComposite.SrcIn);
|
||||
g.setColor(color);
|
||||
@ -734,22 +791,88 @@ final public class MapPanel extends javax.swing.JPanel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintWaypoint(Graphics2D gd, JXMapViewer jxmv, MapWaypoint waypoint) {
|
||||
Color color = getColor(waypoint, currentlySelectedWaypoint);
|
||||
|
||||
// Store computed images in cache for later use
|
||||
BufferedImage image = imageCache.computeIfAbsent(color, k -> {
|
||||
return createWaypointImage(color);
|
||||
});
|
||||
|
||||
Point2D point = jxmv.getTileFactory().geoToPixel(waypoint.getPosition(), jxmv.getZoom());
|
||||
|
||||
public void paintWaypoint(Graphics2D g, JXMapViewer map, MapWaypoint waypoint) {
|
||||
Color color = getColor(waypoint);
|
||||
BufferedImage image;
|
||||
int artifactType = waypoint.getArtifactTypeID();
|
||||
Point2D point = map.getTileFactory().geoToPixel(waypoint.getPosition(), map.getZoom());
|
||||
int x = (int) point.getX();
|
||||
int y = (int) point.getY();
|
||||
|
||||
gd = (Graphics2D) gd.create();
|
||||
gd.drawImage(image, x - image.getWidth() / 2, y - image.getHeight(), null);
|
||||
gd.dispose();
|
||||
if (artifactType == ARTIFACT_TYPE.TSK_GPS_TRACKPOINT.getTypeID()
|
||||
|| artifactType == ARTIFACT_TYPE.TSK_GPS_TRACK.getTypeID()
|
||||
|| artifactType == ARTIFACT_TYPE.TSK_GPS_ROUTE.getTypeID()) {
|
||||
image = dotImageCache.computeIfAbsent(color, k -> {
|
||||
return createTrackDotImage(color);
|
||||
});
|
||||
// Center the dot on the GPS coordinate
|
||||
y -= image.getHeight() / 2;
|
||||
} else {
|
||||
image = waypointImageCache.computeIfAbsent(color, k -> {
|
||||
return createWaypointImage(color);
|
||||
});
|
||||
// Align the bottom of the pin with the GPS coordinate
|
||||
y -= image.getHeight();
|
||||
}
|
||||
// Center image horizontally on image
|
||||
x -= image.getWidth() / 2;
|
||||
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
g2d.drawImage(image, x, y, null);
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Renderer for map track routes
|
||||
*/
|
||||
private class MapTrackRenderer implements Painter<JXMapViewer> {
|
||||
|
||||
private final List<Set<MapWaypoint>> tracks;
|
||||
|
||||
MapTrackRenderer(List<Set<MapWaypoint>> tracks) {
|
||||
this.tracks = tracks;
|
||||
}
|
||||
|
||||
private void drawRoute(Set<MapWaypoint> track, Graphics2D g, JXMapViewer map) {
|
||||
int lastX = 0;
|
||||
int lastY = 0;
|
||||
|
||||
boolean first = true;
|
||||
|
||||
for (MapWaypoint wp : track) {
|
||||
Point2D p = map.getTileFactory().geoToPixel(wp.getPosition(), map.getZoom());
|
||||
int thisX = (int) p.getX();
|
||||
int thisY = (int) p.getY();
|
||||
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
g.drawLine(lastX, lastY, thisX, thisY);
|
||||
}
|
||||
|
||||
lastX = thisX;
|
||||
lastY = thisY;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics2D g, JXMapViewer map, int w, int h) {
|
||||
Graphics2D g2d = (Graphics2D) g.create();
|
||||
|
||||
Rectangle bounds = map.getViewportBounds();
|
||||
g2d.translate(-bounds.x, -bounds.y);
|
||||
|
||||
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
|
||||
g2d.setColor(Color.BLACK);
|
||||
g2d.setStroke(new BasicStroke(2));
|
||||
|
||||
for (Set<MapWaypoint> track : tracks) {
|
||||
drawRoute(track, g2d, map);
|
||||
}
|
||||
|
||||
g2d.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
|
||||
private final GeoPosition position;
|
||||
|
||||
/**
|
||||
* Returns a list of of MapWaypoint objects for the given list of
|
||||
* Returns a list of MapWaypoint objects for the given list of
|
||||
* datamodel.Waypoint objects.
|
||||
*
|
||||
* @param dmWaypoints
|
||||
@ -199,6 +199,13 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
|
||||
return getFormattedDetails(dataModelWaypoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the artifact type for this waypoint's data source
|
||||
*/
|
||||
int getArtifactTypeID() {
|
||||
return dataModelWaypoint.getArtifact().getArtifactTypeID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of JMenuItems for the waypoint. The list list may contain
|
||||
* nulls which should be removed or replaced with JSeparators.
|
||||
|
@ -98,7 +98,7 @@ public final class WaypointBuilder {
|
||||
*
|
||||
* @param wwaypoints This of waypoints.
|
||||
*/
|
||||
void process(List<Waypoint> wwaypoints);
|
||||
void process(List<Waypoint> waypoints);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,7 +44,6 @@ from org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints import Tr
|
||||
from org.sleuthkit.autopsy.datamodel import ContentUtils
|
||||
from org.sleuthkit.autopsy.ingest import IngestModule
|
||||
from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException
|
||||
from org.sleuthkit.autopsy.ingest import DataSourceIngestModule
|
||||
from org.sleuthkit.autopsy.ingest import FileIngestModule
|
||||
from org.sleuthkit.autopsy.ingest import IngestModuleFactoryAdapter
|
||||
from org.sleuthkit.autopsy.ingest import IngestMessage
|
||||
@ -60,9 +59,14 @@ import gpxpy
|
||||
import gpxpy.gpx
|
||||
import gpxpy.parser
|
||||
|
||||
# to get a random filename to prevent race conditions
|
||||
import uuid
|
||||
|
||||
# Factory that defines the name and details of the module and allows Autopsy
|
||||
# to create instances of the modules that will do the analysis.
|
||||
class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
|
||||
|
||||
|
||||
class GPXParserFileIngestModuleFactory(IngestModuleFactoryAdapter):
|
||||
|
||||
moduleName = "GPX Parser"
|
||||
|
||||
@ -75,77 +79,66 @@ class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
|
||||
def getModuleVersionNumber(self):
|
||||
return "1.2"
|
||||
|
||||
def isDataSourceIngestModuleFactory(self):
|
||||
def isFileIngestModuleFactory(self):
|
||||
return True
|
||||
|
||||
def createDataSourceIngestModule(self, ingestOptions):
|
||||
return GPXParserDataSourceIngestModule()
|
||||
def createFileIngestModule(self, ingestOptions):
|
||||
return GPXParserFileIngestModule()
|
||||
|
||||
|
||||
# Data Source-level ingest module. One gets created per data source.
|
||||
class GPXParserDataSourceIngestModule(DataSourceIngestModule):
|
||||
# File level ingest module.
|
||||
class GPXParserFileIngestModule(FileIngestModule):
|
||||
|
||||
logger = Logger.getLogger(GPXParserDataSourceIngestModuleFactory.moduleName)
|
||||
logger = Logger.getLogger(
|
||||
GPXParserFileIngestModuleFactory.moduleName)
|
||||
writeDebugMsgs = False
|
||||
|
||||
def log(self, level, msg):
|
||||
self.logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
|
||||
self.logger.logp(level, self.__class__.__name__,
|
||||
inspect.stack()[1][3], msg)
|
||||
|
||||
def __init__(self):
|
||||
self.context = None
|
||||
|
||||
# Where any setup and configuration is done.
|
||||
def startUp(self, context):
|
||||
self.context = context
|
||||
|
||||
# Where the analysis is done.
|
||||
def process(self, dataSource, progressBar):
|
||||
|
||||
# We don't know how much work there is yet.
|
||||
progressBar.switchToIndeterminate()
|
||||
|
||||
# Get the case database and its blackboard.
|
||||
skCase = Case.getCurrentCase().getSleuthkitCase()
|
||||
blackboard = skCase.getBlackboard()
|
||||
|
||||
# Get any files with a .gpx extension.
|
||||
# It would perhaps be better to get these files by MIME type instead.
|
||||
# RC: It would also be better if this were a file level ingest module so it could process files extracted from archives.
|
||||
fileManager = Case.getCurrentCase().getServices().getFileManager()
|
||||
files = fileManager.findFiles(dataSource, "%.gpx")
|
||||
|
||||
# Update the progress bar now that we know how much work there is to do.
|
||||
numFiles = len(files)
|
||||
if self.writeDebugMsgs: self.log(Level.INFO, "Found " + str(numFiles) + " GPX files")
|
||||
progressBar.switchToDeterminate(numFiles)
|
||||
self.fileCount = 0
|
||||
|
||||
# Get the module name, it will be needed for adding attributes
|
||||
moduleName = GPXParserDataSourceIngestModuleFactory.moduleName
|
||||
self.moduleName = GPXParserFileIngestModuleFactory.moduleName
|
||||
|
||||
# Get the case database and its blackboard.
|
||||
self.skCase = Case.getCurrentCase().getSleuthkitCase()
|
||||
self.blackboard = self.skCase.getBlackboard()
|
||||
|
||||
# Check if a folder for this module is present in the case Temp directory.
|
||||
# If not, create it.
|
||||
dirName = os.path.join(Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module")
|
||||
self.dirName = os.path.join(
|
||||
Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module")
|
||||
try:
|
||||
os.stat(dirName)
|
||||
os.stat(self.dirName)
|
||||
except:
|
||||
os.mkdir(dirName)
|
||||
os.mkdir(self.dirName)
|
||||
|
||||
# Where any setup and configuration is done.
|
||||
|
||||
def startUp(self, context):
|
||||
self.context = context
|
||||
self.fileCount = 0
|
||||
|
||||
# Where the file analysis is done.
|
||||
def process(self, file):
|
||||
if not file.getName().lower().endswith(".gpx"):
|
||||
return IngestModule.ProcessResult.OK
|
||||
|
||||
# Create a temp file name. It appears that we cannot close and delete
|
||||
# this file, but we can overwrite it for each file we need to process.
|
||||
fileName = os.path.join(dirName, "tmp.gpx")
|
||||
|
||||
fileCount = 0;
|
||||
for file in files:
|
||||
fileName = os.path.join(self.dirName, uuid.uuid4().hex + ".gpx")
|
||||
|
||||
# Create a GeoArtifactsHelper for this file.
|
||||
geoArtifactHelper = GeoArtifactsHelper(skCase, moduleName, None, file)
|
||||
geoArtifactHelper = GeoArtifactsHelper(
|
||||
self.skCase, self.moduleName, None, file)
|
||||
|
||||
# Check if the user pressed cancel while we were busy.
|
||||
if self.context.isJobCancelled():
|
||||
return IngestModule.ProcessResult.OK
|
||||
|
||||
if self.writeDebugMsgs: self.log(Level.INFO, "Processing " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
fileCount += 1
|
||||
if self.writeDebugMsgs:
|
||||
self.log(Level.INFO, "Processing " + file.getUniquePath() +
|
||||
" (objID = " + str(file.getId()) + ")")
|
||||
|
||||
# Write the file so that it can be parsed by gpxpy.
|
||||
localFile = File(fileName)
|
||||
@ -155,13 +148,19 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule):
|
||||
gpxfile = open(fileName)
|
||||
try:
|
||||
gpx = gpxpy.parse(gpxfile)
|
||||
if self.writeDebugMsgs: self.log(Level.INFO, "Parsed " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
if self.writeDebugMsgs:
|
||||
self.log(Level.INFO, "Parsed " + file.getUniquePath() +
|
||||
" (objID = " + str(file.getId()) + ")")
|
||||
except Exception as e:
|
||||
self.log(Level.WARNING, "Error parsing file " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
|
||||
continue
|
||||
self.log(Level.WARNING, "Error parsing file " + file.getUniquePath() +
|
||||
" (objID = " + str(file.getId()) + "):" + str(e))
|
||||
return IngestModule.ProcessResult.ERROR
|
||||
|
||||
if gpx:
|
||||
if self.writeDebugMsgs: self.log(Level.INFO, "Processing tracks from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
if self.writeDebugMsgs:
|
||||
self.log(Level.INFO, "Processing tracks from " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
|
||||
for track in gpx.tracks:
|
||||
for segment in track.segments:
|
||||
geoPointList = GeoTrackPoints()
|
||||
@ -174,59 +173,82 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule):
|
||||
timeStamp = 0
|
||||
try:
|
||||
if (point.time != None):
|
||||
timeStamp = long(time.mktime(point.time.timetuple()))
|
||||
timeStamp = long(time.mktime(
|
||||
point.time.timetuple()))
|
||||
except Exception as e:
|
||||
self.log(Level.WARNING, "Error getting track timestamp from " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
|
||||
self.log(Level.WARNING, "Error getting track timestamp from " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
|
||||
|
||||
geoPointList.addPoint(TrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
|
||||
geoPointList.addPoint(TrackPoint(
|
||||
point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
|
||||
|
||||
try:
|
||||
geoArtifactHelper.addTrack("Track", geoPointList, None)
|
||||
except Blackboard.BlackboardException as e:
|
||||
self.log(Level.SEVERE, "Error posting GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
self.log(Level.SEVERE, "Error posting GPS track artifact for " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
except TskCoreException as e:
|
||||
self.log(Level.SEVERE, "Error creating GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
self.log(Level.SEVERE, "Error creating GPS track artifact for " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
|
||||
if self.writeDebugMsgs:
|
||||
self.log(Level.INFO, "Processing waypoints from " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
|
||||
if self.writeDebugMsgs: self.log(Level.INFO, "Processing waypoints from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
for waypoint in gpx.waypoints:
|
||||
|
||||
try:
|
||||
art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
|
||||
art = file.newArtifact(
|
||||
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
|
||||
|
||||
attributes = ArrayList()
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, waypoint.latitude))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, waypoint.longitude))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG.getTypeID(), moduleName, "Waypoint"))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, waypoint.name))
|
||||
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "GPXParser"))
|
||||
attributes.add(BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), self.moduleName, waypoint.latitude))
|
||||
attributes.add(BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), self.moduleName, waypoint.longitude))
|
||||
attributes.add(BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG.getTypeID(), self.moduleName, "Waypoint"))
|
||||
attributes.add(BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), self.moduleName, waypoint.name))
|
||||
attributes.add(BlackboardAttribute(
|
||||
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), self.moduleName, "GPXParser"))
|
||||
art.addAttributes(attributes)
|
||||
|
||||
blackboard.postArtifact(art, moduleName)
|
||||
self.blackboard.postArtifact(art, self.moduleName)
|
||||
|
||||
except Blackboard.BlackboardException as e:
|
||||
self.log(Level.SEVERE, "Error posting GPS bookmark artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
self.log(Level.SEVERE, "Error posting GPS bookmark artifact for " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
except TskCoreException as e:
|
||||
self.log(Level.SEVERE, "Error creating GPS bookmark artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
self.log(Level.SEVERE, "Error creating GPS bookmark artifact for " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
|
||||
if self.writeDebugMsgs:
|
||||
self.log(Level.INFO, "Processing routes from " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
|
||||
if self.writeDebugMsgs: self.log(Level.INFO, "Processing routes from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
|
||||
for route in gpx.routes:
|
||||
|
||||
geoWaypoints = GeoWaypoints()
|
||||
|
||||
for point in route.points:
|
||||
geoWaypoints.addPoint(Waypoint(point.latitude, point.longitude, point.elevation, point.name))
|
||||
geoWaypoints.addPoint(
|
||||
Waypoint(point.latitude, point.longitude, point.elevation, point.name))
|
||||
|
||||
try:
|
||||
geoArtifactHelper.addRoute(None, None, geoWaypoints, None)
|
||||
except Blackboard.BlackboardException as e:
|
||||
self.log("Error posting GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
self.log("Error posting GPS route artifact for " + file.getUniquePath() +
|
||||
" (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
except TskCoreException as e:
|
||||
self.log(Level.SEVERE, "Error creating GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
self.log(Level.SEVERE, "Error creating GPS route artifact for " +
|
||||
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
|
||||
|
||||
# Update the progress bar.
|
||||
progressBar.progress(fileCount)
|
||||
self.fileCount += 1
|
||||
return IngestModule.ProcessResult.OK
|
||||
|
||||
# Post a message to the ingest messages inbox.
|
||||
message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, moduleName, "Processed %d files" % fileCount)
|
||||
IngestServices.getInstance().postMessage(message)
|
||||
return IngestModule.ProcessResult.OK;
|
||||
def shutDown(self):
|
||||
message = IngestMessage.createMessage(
|
||||
IngestMessage.MessageType.DATA, GPXParserFileIngestModuleFactory.moduleName,
|
||||
str(self.fileCount) + " files found")
|
||||
ingestServices = IngestServices.getInstance().postMessage(message)
|
||||
|
@ -23,8 +23,6 @@ There is no need for manual installation of additional dependencies if the Windo
|
||||
|
||||
If you want the Japanese localized version, you must have the Japanese language pack (http://support.microsoft.com/kb/972813) installed and the default locale set to JA. (http://windows.microsoft.com/en-us/windows/change-system-locale#1TC=windows-7).
|
||||
|
||||
Refer to the KNOWN_ISSUES.txt file for known bugs that could cause investigation problems.
|
||||
|
||||
|
||||
SUPPORT
|
||||
|
||||
|
BIN
thirdparty/IcePDF 6.2.2/batik-awt-util-1.6.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/batik-awt-util-1.6.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/batik-dom-1.6.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/batik-dom-1.6.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/batik-svg-dom-1.6.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/batik-svg-dom-1.6.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/batik-svggen-1.6.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/batik-svggen-1.6.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/batik-util-1.6.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/batik-util-1.6.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/batik-xml-1.6.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/batik-xml-1.6.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/bcpkix-jdk15on-1.54.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/bcpkix-jdk15on-1.54.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/bcprov-ext-jdk15on-1.54.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/bcprov-ext-jdk15on-1.54.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/bcprov-jdk15on-1.54.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/bcprov-jdk15on-1.54.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/icepdf-core-6.2.2.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/icepdf-core-6.2.2.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/icepdf-viewer-6.2.2.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/icepdf-viewer-6.2.2.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/jai_core-1.1.3.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/jai_core-1.1.3.jar
vendored
Executable file
Binary file not shown.
BIN
thirdparty/IcePDF 6.2.2/jai_imageio-1.1.jar
vendored
Executable file
BIN
thirdparty/IcePDF 6.2.2/jai_imageio-1.1.jar
vendored
Executable file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user