Merge branch 'develop' into 6267_null_exif_geodata

This commit is contained in:
Ethan Roseman 2020-04-22 10:53:06 -04:00
commit 3ddab0ae57
34 changed files with 741 additions and 229 deletions

View File

@ -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}" />

View File

@ -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

View File

@ -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>

View File

@ -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() {

View File

@ -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();

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -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;

View 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());
}
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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;

View File

@ -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));

View File

@ -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;
}
/**

View File

@ -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);
}
}
}

View File

@ -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();
}
}
}

View File

@ -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.

View File

@ -98,7 +98,7 @@ public final class WaypointBuilder {
*
* @param wwaypoints This of waypoints.
*/
void process(List<Waypoint> wwaypoints);
void process(List<Waypoint> waypoints);
}
/**

View File

@ -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,158 +79,176 @@ 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")
fileName = os.path.join(self.dirName, uuid.uuid4().hex + ".gpx")
fileCount = 0;
for file in files:
# Create a GeoArtifactsHelper for this file.
geoArtifactHelper = GeoArtifactsHelper(
self.skCase, self.moduleName, None, file)
# Create a GeoArtifactsHelper for this file.
geoArtifactHelper = GeoArtifactsHelper(skCase, moduleName, None, file)
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing " + file.getUniquePath() +
" (objID = " + str(file.getId()) + ")")
# Check if the user pressed cancel while we were busy.
if self.context.isJobCancelled():
return IngestModule.ProcessResult.OK
# Write the file so that it can be parsed by gpxpy.
localFile = File(fileName)
ContentUtils.writeToFile(file, localFile)
if self.writeDebugMsgs: self.log(Level.INFO, "Processing " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
fileCount += 1
# Send the file to gpxpy for parsing.
gpxfile = open(fileName)
try:
gpx = gpxpy.parse(gpxfile)
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))
return IngestModule.ProcessResult.ERROR
# Write the file so that it can be parsed by gpxpy.
localFile = File(fileName)
ContentUtils.writeToFile(file, localFile)
if gpx:
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing tracks from " +
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
# Send the file to gpxpy for parsing.
gpxfile = open(fileName)
try:
gpx = gpxpy.parse(gpxfile)
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
for track in gpx.tracks:
for segment in track.segments:
geoPointList = GeoTrackPoints()
for point in segment.points:
if gpx:
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()
for point in segment.points:
elevation = 0
if point.elevation != None:
elevation = point.elevation
timeStamp = 0
try:
if (point.time != None):
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))
geoPointList.addPoint(TrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
elevation = 0
if point.elevation != None:
elevation = point.elevation
timeStamp = 0
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())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
if (point.time != None):
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))
if self.writeDebugMsgs: self.log(Level.INFO, "Processing waypoints from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
for waypoint in gpx.waypoints:
geoPointList.addPoint(TrackPoint(
point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
try:
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"))
art.addAttributes(attributes)
blackboard.postArtifact(art, moduleName)
geoArtifactHelper.addTrack("Track", geoPointList, None)
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 track 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 track 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()) + ")")
for route in gpx.routes:
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing waypoints from " +
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
geoWaypoints = GeoWaypoints()
for waypoint in gpx.waypoints:
for point in route.points:
geoWaypoints.addPoint(Waypoint(point.latitude, point.longitude, point.elevation, point.name))
try:
art = file.newArtifact(
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
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())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
attributes = ArrayList()
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)
# Update the progress bar.
progressBar.progress(fileCount)
self.blackboard.postArtifact(art, self.moduleName)
# 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;
except Blackboard.BlackboardException as e:
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())
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))
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())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS route artifact for " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
self.fileCount += 1
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)

View File

@ -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

Binary file not shown.

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

Binary file not shown.

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

Binary file not shown.

BIN
thirdparty/IcePDF 6.2.2/batik-xml-1.6.jar vendored Executable file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
thirdparty/IcePDF 6.2.2/icepdf-core-6.2.2.jar vendored Executable file

Binary file not shown.

Binary file not shown.

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

Binary file not shown.