diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java
index 18fd2c6202..337fa49f0b 100644
--- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java
+++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashDbImportDatabaseDialog.java
@@ -22,6 +22,7 @@ import java.awt.Dimension;
import java.awt.Toolkit;
import java.io.File;
import java.io.IOException;
+import java.nio.file.Paths;
import java.util.logging.Level;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
@@ -31,6 +32,7 @@ import org.apache.commons.io.FilenameUtils;
import org.openide.util.NbBundle;
import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.autopsy.coreutils.ModuleSettings;
+import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType;
import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDbManagerException;
@@ -249,9 +251,16 @@ final class HashDbImportDatabaseDialog extends javax.swing.JDialog {
}// //GEN-END:initComponents
private void openButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_openButtonActionPerformed
+ String lastBaseDirectory = Paths.get(PlatformUtil.getUserConfigDirectory(), "HashDatabases").toString();
if (ModuleSettings.settingExists(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)) {
- fileChooser.setCurrentDirectory(new File(ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY)));
+ lastBaseDirectory = ModuleSettings.getConfigSetting(ModuleSettings.MAIN_SETTINGS, LAST_FILE_PATH_KEY);
}
+ File hashDbFolder = new File(lastBaseDirectory);
+ // create the folder if it doesn't exist
+ if (!hashDbFolder.exists()) {
+ hashDbFolder.mkdir();
+ }
+ fileChooser.setCurrentDirectory(hashDbFolder);
if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
File databaseFile = fileChooser.getSelectedFile();
try {
diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties
index ba477498c3..6e920ad631 100644
--- a/Core/src/org/sleuthkit/autopsy/report/Bundle.properties
+++ b/Core/src/org/sleuthkit/autopsy/report/Bundle.properties
@@ -225,7 +225,8 @@ ReportHTML.writeSum.noCaseNum=No case number
ReportBodyFile.generateReport.srcModuleName.text=TSK Body File
ReportExcel.endReport.srcModuleName.text=Excel Report
ReportHTML.writeIndex.srcModuleName.text=HTML Report
-ReportKML.genReport.srcModuleName.text=KML Report
+ReportKML.genReport.srcModuleName.text=Geospatial Data
+ReportKML.genReport.reportName=KML Report
ReportGenerator.artTableColHdr.extension.text=Extension
ReportGenerator.artTableColHdr.mimeType.text=MIME Type
ReportGenerator.artTableColHdr.processorArchitecture.text=Processor Architecture
diff --git a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties
index 6ff657b68a..a877c52899 100644
--- a/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties
+++ b/Core/src/org/sleuthkit/autopsy/report/Bundle_ja.properties
@@ -188,7 +188,7 @@ ReportExcel.endReport.srcModuleName.text=Excel\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.extension.text=\u62e1\u5f35\u5b50
ReportGenerator.artTableColHdr.mimeType.text=MIME\u30bf\u30a4\u30d7
ReportHTML.writeIndex.srcModuleName.text=HTML\u30ec\u30dd\u30fc\u30c8
-ReportKML.genReport.srcModuleName.text=KML\u30ec\u30dd\u30fc\u30c8
+ReportKML.genReport.reportName=KML\u30ec\u30dd\u30fc\u30c8
ReportGenerator.artTableColHdr.associatedArtifact=\u95a2\u4fc2\u3059\u308b\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8
ReportGenerator.artTableColHdr.count=\u30ab\u30a6\u30f3\u30c8
ReportGenerator.artTableColHdr.devMake=\u6a5f\u5668\u578b\u540d
diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java
index abdd7dee96..44185bfc94 100644
--- a/Core/src/org/sleuthkit/autopsy/report/ReportKML.java
+++ b/Core/src/org/sleuthkit/autopsy/report/ReportKML.java
@@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
- * Copyright 2014 Basis Technology Corp.
+ * Copyright 2014-2016 Basis Technology Corp.
* contact: carrier sleuthkit org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,33 +27,56 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import org.sleuthkit.datamodel.*;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.datamodel.BlackboardArtifact;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.SimpleDateFormat;
import java.util.logging.Level;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
-import org.apache.commons.lang.StringEscapeUtils;
+import org.jdom2.CDATA;
+import org.openide.filesystems.FileUtil;
/**
- * Generates a KML file based on geo coordinates store in blackboard.
+ * Generates a KML file based on geospatial information from the BlackBoard.
*/
class ReportKML implements GeneralReportModule {
private static final Logger logger = Logger.getLogger(ReportKML.class.getName());
+ private static final String KML_STYLE_FILE = "style.kml";
+ private static final String REPORT_KML = "ReportKML.kml";
+ private static final String STYLESHEETS_PATH = "/org/sleuthkit/autopsy/report/stylesheets/";
private static ReportKML instance = null;
private Case currentCase;
private SleuthkitCase skCase;
- private String reportPath;
+ private final SimpleDateFormat kmlDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ private Namespace ns;
+ private final String SEP = "
";
+
+ private enum FeatureColor {
+ RED("style.kml#redFeature"),
+ GREEN("style.kml#greenFeature"),
+ BLUE("style.kml#blueFeature"),
+ PURPLE("style.kml#purpleFeature"),
+ WHITE("style.kml#whiteFeature"),
+ YELLOW("style.kml#yellowFeature");
+ private String color;
+
+ FeatureColor(String color) {
+ this.color = color;
+ }
+
+ String getColor() {
+ return this.color;
+ }
+ }
// Hidden constructor for the report
private ReportKML() {
@@ -80,279 +103,684 @@ class ReportKML implements GeneralReportModule {
progressPanel.setIndeterminate(false);
progressPanel.start();
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying"));
- reportPath = baseReportDir + "ReportKML.kml"; //NON-NLS
- String reportPath2 = baseReportDir + "ReportKML.txt"; //NON-NLS
+ String kmlFileFullPath = baseReportDir + REPORT_KML; //NON-NLS
currentCase = Case.getCurrentCase();
skCase = currentCase.getSleuthkitCase();
progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.loading"));
- // Check if ingest has finished
- String ingestwarning = "";
- if (IngestManager.getInstance().isIngestRunning()) {
- ingestwarning = NbBundle.getMessage(this.getClass(), "ReportBodyFile.ingestWarning.text");
- }
+
progressPanel.setMaximumProgress(5);
progressPanel.increment();
- // @@@ BC: I don't get why we do this in two passes.
- // Why not just print the coordinates as we find them and make some utility methods to do the printing?
- // Should pull out time values for all of these points and store in TimeSpan element
+ ns = Namespace.getNamespace("", "http://www.opengis.net/kml/2.2"); //NON-NLS
+
+ Element kml = new Element("kml", ns); //NON-NLS
+ kml.addNamespaceDeclaration(Namespace.getNamespace("gx", "http://www.google.com/kml/ext/2.2")); //NON-NLS
+ kml.addNamespaceDeclaration(Namespace.getNamespace("kml", "http://www.opengis.net/kml/2.2")); //NON-NLS
+ kml.addNamespaceDeclaration(Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom")); //NON-NLS
+ Document kmlDocument = new Document(kml);
+
+ Element document = new Element("Document", ns); //NON-NLS
+ kml.addContent(document);
+
+ Element name = new Element("name", ns); //NON-NLS
+ ReportBranding rb = new ReportBranding();
+ name.setText(rb.getReportTitle() + " KML"); //NON-NLS
+ document.addContent(name);
+
+ // Check if ingest has finished
+ if (IngestManager.getInstance().isIngestRunning()) {
+ Element ingestwarning = new Element("snippet", ns); //NON-NLS
+ ingestwarning.addContent(NbBundle.getMessage(this.getClass(), "ReportBodyFile.ingestWarning.text")); //NON-NLS
+ document.addContent(ingestwarning);
+ }
+
+ // Create folder structure
+ Element gpsExifMetadataFolder = new Element("Folder", ns); //NON-NLS
+ CDATA cdataExifMetadataFolder = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/camera-icon-16.png"); //NON-NLS
+ Element hrefExifMetadata = new Element("href", ns).addContent(cdataExifMetadataFolder); //NON-NLS
+ gpsExifMetadataFolder.addContent(new Element("Icon", ns).addContent(hrefExifMetadata)); //NON-NLS
+
+ Element gpsBookmarksFolder = new Element("Folder", ns); //NON-NLS
+ CDATA cdataBookmarks = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gpsfav.png"); //NON-NLS
+ Element hrefBookmarks = new Element("href", ns).addContent(cdataBookmarks); //NON-NLS
+ gpsBookmarksFolder.addContent(new Element("Icon", ns).addContent(hrefBookmarks)); //NON-NLS
+
+ Element gpsLastKnownLocationFolder = new Element("Folder", ns); //NON-NLS
+ CDATA cdataLastKnownLocation = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-lastlocation.png"); //NON-NLS
+ Element hrefLastKnownLocation = new Element("href", ns).addContent(cdataLastKnownLocation); //NON-NLS
+ gpsLastKnownLocationFolder.addContent(new Element("Icon", ns).addContent(hrefLastKnownLocation)); //NON-NLS
+
+ Element gpsRouteFolder = new Element("Folder", ns); //NON-NLS
+ CDATA cdataRoute = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-trackpoint.png"); //NON-NLS
+ Element hrefRoute = new Element("href", ns).addContent(cdataRoute); //NON-NLS
+ gpsRouteFolder.addContent(new Element("Icon", ns).addContent(hrefRoute)); //NON-NLS
+
+ Element gpsSearchesFolder = new Element("Folder", ns); //NON-NLS
+ CDATA cdataSearches = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-search.png"); //NON-NLS
+ Element hrefSearches = new Element("href", ns).addContent(cdataSearches); //NON-NLS
+ gpsSearchesFolder.addContent(new Element("Icon", ns).addContent(hrefSearches)); //NON-NLS
+
+ Element gpsTrackpointsFolder = new Element("Folder", ns); //NON-NLS
+ CDATA cdataTrackpoints = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-trackpoint.png"); //NON-NLS
+ Element hrefTrackpoints = new Element("href", ns).addContent(cdataTrackpoints); //NON-NLS
+ gpsTrackpointsFolder.addContent(new Element("Icon", ns).addContent(hrefTrackpoints)); //NON-NLS
+
+ gpsExifMetadataFolder.addContent(new Element("name", ns).addContent("EXIF Metadata")); //NON-NLS
+ gpsBookmarksFolder.addContent(new Element("name", ns).addContent("GPS Bookmarks")); //NON-NLS
+ gpsLastKnownLocationFolder.addContent(new Element("name", ns).addContent("GPS Last Known Location")); //NON-NLS
+ gpsRouteFolder.addContent(new Element("name", ns).addContent("GPS Routes")); //NON-NLS
+ gpsSearchesFolder.addContent(new Element("name", ns).addContent("GPS Searches")); //NON-NLS
+ gpsTrackpointsFolder.addContent(new Element("name", ns).addContent("GPS Trackpoints")); //NON-NLS
+
+ document.addContent(gpsExifMetadataFolder);
+ document.addContent(gpsBookmarksFolder);
+ document.addContent(gpsLastKnownLocationFolder);
+ document.addContent(gpsRouteFolder);
+ document.addContent(gpsSearchesFolder);
+ document.addContent(gpsTrackpointsFolder);
+
+ /**
+ * In the following code, nulls are okay, and are handled when we go to
+ * write out the KML feature. Nulls are expected to be returned from any
+ * method where the artifact is not found and is handled in the
+ * individual feature creation methods. This is done because we don't
+ * know beforehand which attributes will be included for which artifact,
+ * as anyone could write a module that adds additional attributes to an
+ * artifact.
+ *
+ */
try {
- try (BufferedWriter out = new BufferedWriter(new FileWriter(reportPath2))) {
-
- double lat = 0; // temp latitude
- double lon = 0; //temp longitude
- AbstractFile aFile;
- String geoPath = ""; // will hold values of images to put in kml
- String imageName = "";
-
- File f;
- for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)) {
- lat = 0;
- lon = 0;
- geoPath = "";
- String extractedToPath;
- for (BlackboardAttribute attribute : artifact.getAttributes()) {
- if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
- {
-
- lat = attribute.getValueDouble();
- }
- if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
- {
- lon = attribute.getValueDouble();
- }
- }
- if (lon != 0 && lat != 0) {
- aFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
-
- if (aFile != null) {
- extractedToPath = reportPath + aFile.getName();
- geoPath = extractedToPath;
- f = new File(extractedToPath);
- f.createNewFile();
- copyFileUsingStream(aFile, f);
- imageName = aFile.getName();
- }
- out.write(String.valueOf(lat));
- out.write(";");
- out.write(String.valueOf(lon));
- out.write(";");
- out.write(String.valueOf(geoPath));
- out.write(";");
- out.write(String.valueOf(imageName));
- out.write("\n");
- // lat lon path name
+ for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)) {
+ Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED);
+ String desc = getDescriptionFromArtifact(artifact, "EXIF Metadata With Locations"); //NON-NLS
+ Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
+ Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
+ Element point = makePoint(lat, lon, getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE));
+ Path destination = null;
+ if (lat != null && lat != 0.0 && lon != null && lon != 0.0) {
+ AbstractFile abstractFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
+ if (abstractFile != null) {
+ destination = Paths.get(baseReportDir, abstractFile.getName());
+ copyFileUsingStream(abstractFile, destination.toFile());
}
+ String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
+ gpsExifMetadataFolder.addContent(makePlacemarkWithPicture(abstractFile.getName(), FeatureColor.RED, desc, timestamp, point, destination, formattedCoordinates));
}
- for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) {
- lat = 0;
- lon = 0;
- for (BlackboardAttribute attribute : artifact.getAttributes()) {
- if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
- {
- lat = attribute.getValueDouble();
- }
- if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
- {
- lon = attribute.getValueDouble();
- }
- }
- if (lon != 0 && lat != 0) {
- out.write(lat + ";" + lon + "\n");
- }
- }
-
- for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) {
- lat = 0;
- lon = 0;
- double destlat = 0;
- double destlon = 0;
- String name = "";
- String location = "";
- for (BlackboardAttribute attribute : artifact.getAttributes()) {
- if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude
- {
- lat = attribute.getValueDouble();
- } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude
- {
- destlat = attribute.getValueDouble();
- } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude
- {
- lon = attribute.getValueDouble();
- } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude
- {
- destlon = attribute.getValueDouble();
- } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID()) //longitude
- {
- name = attribute.getValueString();
- } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()) //longitude
- {
- location = attribute.getValueString();
- }
- }
-
- // @@@ Should do something more fancy with these in KML and store them as a single point.
- String display = name;
- if (display.isEmpty()) {
- display = location;
- }
-
- if (lon != 0 && lat != 0) {
- out.write(NbBundle.getMessage(this.getClass(), "ReportKML.latLongStartPoint", lat, lon, display));
- }
- if (destlat != 0 && destlon != 0) {
- out.write(NbBundle.getMessage(this.getClass(), "ReportKML.latLongEndPoint", destlat, destlon,
- display));
- }
- }
-
- out.flush();
-
- progressPanel.increment();
- /*
- * Step 1: generate XML stub
- */
- Namespace ns = Namespace.getNamespace("", "http://earth.google.com/kml/2.2"); //NON-NLS
- // kml
- Element kml = new Element("kml", ns); //NON-NLS
- Document kmlDocument = new Document(kml);
-
- // Document
- Element document = new Element("Document", ns); //NON-NLS
- kml.addContent(document);
-
- // name
- Element name = new Element("name", ns); //NON-NLS
- name.setText("Java Generated KML Document"); //NON-NLS
- document.addContent(name);
-
- /*
- * Step 2: add in Style elements
- */
- // Style
- Element style = new Element("Style", ns); //NON-NLS
- style.setAttribute("id", "redIcon"); //NON-NLS
- document.addContent(style);
-
- // IconStyle
- Element iconStyle = new Element("IconStyle", ns); //NON-NLS
- style.addContent(iconStyle);
-
- // color
- Element color = new Element("color", ns); //NON-NLS
- color.setText("990000ff"); //NON-NLS
- iconStyle.addContent(color);
-
- // Icon
- Element icon = new Element("Icon", ns); //NON-NLS
- iconStyle.addContent(icon);
-
- // href
- Element href = new Element("href", ns); //NON-NLS
- href.setText("http://www.cs.mun.ca/~hoeber/teaching/cs4767/notes/02.1-kml/circle.png"); //NON-NLS
- icon.addContent(href);
- progressPanel.increment();
- /*
- * Step 3: read data from source location and add in a Placemark
- * for each data element
- */
-
- File file = new File(reportPath2);
- try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
- String line = reader.readLine();
- while (line != null) {
- String[] lineParts = line.split(";");
- if (lineParts.length > 1) {
- String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon
- // Placemark
- Element placemark = new Element("Placemark", ns); //NON-NLS
- document.addContent(placemark);
-
- if (lineParts.length == 4) {
- // name
- Element pmName = new Element("name", ns); //NON-NLS
- pmName.setText(lineParts[3].trim());
- placemark.addContent(pmName);
-
- String savedPath = lineParts[2].trim();
- if (savedPath.isEmpty() == false) {
- // Path
- Element pmPath = new Element("Path", ns); //NON-NLS
- pmPath.setText(savedPath);
- placemark.addContent(pmPath);
-
- // description
- Element pmDescription = new Element("description", ns); //NON-NLS
- String xml = "
" + featureType + ""); //NON-NLS
+
+ String name = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
+ if (name != null && !name.isEmpty()) {
+ result.append("Name: ").append(name).append(SEP); //NON-NLS
+ }
+
+ String location = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION);
+ if (location != null && !location.isEmpty()) {
+ result.append("Location: ").append(location).append(SEP); //NON-NLS
+ }
+
+ Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
+ if (timestamp != null) {
+ result.append("Timestamp: ").append(getTimeStamp(timestamp)).append(SEP); //NON-NLS
+ result.append("Unix timestamp: ").append(timestamp).append(SEP); //NON-NLS
+ }
+
+ Long startingTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START);
+ if (startingTimestamp != null) {
+ result.append("Starting Timestamp: ").append(getTimeStamp(startingTimestamp)).append(SEP); //NON-NLS
+ result.append("Starting Unix timestamp: ").append(startingTimestamp).append(SEP); //NON-NLS
+ }
+
+ Long endingTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END);
+ if (endingTimestamp != null) {
+ result.append("Ending Timestamp: ").append(getTimeStamp(endingTimestamp)).append(SEP); //NON-NLS
+ result.append("Ending Unix timestamp: ").append(endingTimestamp).append(SEP); //NON-NLS
+ }
+
+ Long createdTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED);
+ if (createdTimestamp != null) {
+ result.append("Created Timestamp: ").append(getTimeStamp(createdTimestamp)).append(SEP); //NON-NLS
+ result.append("Created Unix timestamp: ").append(createdTimestamp).append(SEP); //NON-NLS
+ }
+
+ Double latitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
+ if (latitude != null) {
+ result.append("Latitude: ").append(latitude).append(SEP); //NON-NLS
+ }
+
+ Double longitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
+ if (longitude != null) {
+ result.append("Longitude: ").append(longitude).append(SEP); //NON-NLS
+ }
+
+ Double latitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
+ if (latitudeStart != null) {
+ result.append("Latitude Start: ").append(latitudeStart).append(SEP); //NON-NLS
+ }
+
+ Double longitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
+ if (longitudeStart != null) {
+ result.append("Longitude Start: ").append(longitudeStart).append(SEP); //NON-NLS
+ }
+
+ Double latitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
+ if (latitudeEnd != null) {
+ result.append("Latitude End: ").append(latitudeEnd).append(SEP); //NON-NLS
+ }
+
+ Double longitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
+ if (longitudeEnd != null) {
+ result.append("Longitude End: ").append(longitudeEnd).append(SEP); //NON-NLS
+ }
+
+ Double velocity = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_VELOCITY);
+ if (velocity != null) {
+ result.append("Velocity: ").append(velocity).append(SEP); //NON-NLS
+ }
+
+ Double altitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
+ if (altitude != null) {
+ result.append("Altitude: ").append(altitude).append(SEP); //NON-NLS
+ }
+
+ Double bearing = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_BEARING);
+ if (bearing != null) {
+ result.append("Bearing: ").append(bearing).append(SEP); //NON-NLS
+ }
+
+ Integer hPrecision = getInteger(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_HPRECISION);
+ if (hPrecision != null) {
+ result.append("Horizontal Precision Figure of Merit: ").append(hPrecision).append(SEP); //NON-NLS
+ }
+
+ Integer vPrecision = getInteger(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_VPRECISION);
+ if (vPrecision != null) {
+ result.append("Vertical Precision Figure of Merit: ").append(vPrecision).append(SEP); //NON-NLS
+ }
+
+ String mapDatum = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_MAPDATUM);
+ if (mapDatum != null && !mapDatum.isEmpty()) {
+ result.append("Map Datum: ").append(mapDatum).append(SEP); //NON-NLS
+ }
+
+ String programName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME);
+ if (programName != null && !programName.isEmpty()) {
+ result.append("Reported by: ").append(programName).append(SEP); //NON-NLS
+ }
+
+ String flag = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG);
+ if (flag != null && !flag.isEmpty()) {
+ result.append("Flag: ").append(flag).append(SEP); //NON-NLS
+ }
+
+ String pathSource = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_SOURCE);
+ if (pathSource != null && !pathSource.isEmpty()) {
+ result.append("Source: ").append(pathSource).append(SEP); //NON-NLS
+ }
+
+ String deviceMake = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE);
+ if (deviceMake != null && !deviceMake.isEmpty()) {
+ result.append("Device Make: ").append(deviceMake).append(SEP); //NON-NLS
+ }
+
+ String deviceModel = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
+ if (deviceModel != null && !deviceModel.isEmpty()) {
+ result.append("Device Model: ").append(deviceModel).append(SEP); //NON-NLS
+ }
+
+ return result.toString();
+ }
+
+ private String getTimeStamp(long timeStamp) {
+ return kmlDateFormat.format(new java.util.Date(timeStamp * 1000));
+ }
+
+ /**
+ * Create a Point for use in a Placemark. Note in this method altitude is
+ * ignored, as Google Earth apparently has trouble using altitudes for
+ * LineStrings, though the parameters are still in the call. Also note that
+ * any null value passed in will be set to 0.0, under the idea that it is
+ * better to show some data with gaps, than to show nothing at all.
+ *
+ * @param latitude point latitude
+ * @param longitude point longitude
+ * @param altitude point altitude. Currently ignored.
+ *
+ * @return the Point as an Element
+ */
+ private Element makePoint(Double latitude, Double longitude, Double altitude) {
+ if (latitude == null) {
+ latitude = 0.0;
+ }
+ if (longitude == null) {
+ longitude = 0.0;
+ }
+ if (altitude == null) {
+ altitude = 0.0;
+ }
+ Element point = new Element("Point", ns); //NON-NLS
+
+ // KML uses lon, lat. Deliberately reversed.
+ Element coordinates = new Element("coordinates", ns).addContent(longitude + "," + latitude + "," + altitude); //NON-NLS
+
+ if (altitude != 0) {
+ /*
+ Though we are including a non-zero altitude, clamp it to the
+ ground because inaccuracies from the GPS data can cause the terrain
+ to occlude points when zoomed in otherwise. Show the altitude, but
+ keep the point clamped to the ground. We may change this later for
+ flying GPS sensors.
+ */
+ Element altitudeMode = new Element("altitudeMode", ns).addContent("clampToGround"); //NON-NLS
+ point.addContent(altitudeMode);
+ }
+ point.addContent(coordinates);
+
+ return point;
+ }
+
+ /**
+ * Create a LineString for use in a Placemark. Note in this method, start
+ * and stop altitudes get ignored, as Google Earth apparently has trouble
+ * using altitudes for LineStrings, though the parameters are still in the
+ * call. Also note that any null value passed in will be set to 0.0, under
+ * the idea that it is better to show some data with gaps, than to show
+ * nothing at all.
+ *
+ * @param startLatitude Starting latitude
+ * @param startLongitude Starting longitude
+ * @param startAltitude Starting altitude. Currently ignored.
+ * @param stopLatitude Ending latitude
+ * @param stopLongitude Ending longitude
+ * @param stopAltitude Ending altitude. Currently ignored.
+ *
+ * @return the Line as an Element
+ */
+ private Element makeLineString(Double startLatitude, Double startLongitude, Double startAltitude, Double stopLatitude, Double stopLongitude, Double stopAltitude) {
+ if (startLatitude == null) {
+ startLatitude = 0.0;
+ }
+ if (startLongitude == null) {
+ startLongitude = 0.0;
+ }
+ if (startAltitude == null) {
+ startAltitude = 0.0;
+ }
+ if (stopLatitude == null) {
+ stopLatitude = 0.0;
+ }
+ if (stopLongitude == null) {
+ stopLongitude = 0.0;
+ }
+ if (stopAltitude == null) {
+ stopAltitude = 0.0;
+ }
+
+ Element lineString = new Element("LineString", ns); //NON-NLS
+ lineString.addContent(new Element("extrude", ns).addContent("1")); //NON-NLS
+ lineString.addContent(new Element("tessellate", ns).addContent("1")); //NON-NLS
+ lineString.addContent(new Element("altitudeMode", ns).addContent("clampToGround")); //NON-NLS
+ // KML uses lon, lat. Deliberately reversed.
+ lineString.addContent(new Element("coordinates", ns).addContent(
+ startLongitude + "," + startLatitude + ",0.0,"
+ + stopLongitude + "," + stopLatitude + ",0.0")); //NON-NLS
+ return lineString;
+ }
+
+ /**
+ * Make a Placemark for use in displaying features. Takes a
+ * coordinate-bearing feature (Point, LineString, etc) and places it in the
+ * Placemark element.
+ *
+ * @param name Placemark name
+ * @param color Placemark color
+ * @param description Description for the info bubble on the map
+ * @param timestamp Placemark timestamp
+ * @param feature The feature to show. Could be Point, LineString, etc.
+ * @param coordinates The coordinates to display in the list view snippet
+ *
+ * @return the entire KML placemark
+ */
+ private Element makePlacemark(String name, FeatureColor color, String description, Long timestamp, Element feature, String coordinates) {
+ Element placemark = new Element("Placemark", ns); //NON-NLS
+ if (name != null && !name.isEmpty()) {
+ placemark.addContent(new Element("name", ns).addContent(name)); //NON-NLS
+ } else if (timestamp != null) {
+ placemark.addContent(new Element("name", ns).addContent(getTimeStamp(timestamp))); //NON-NLS
+ } else {
+ placemark.addContent(new Element("name", ns).addContent("")); //NON-NLS
+ }
+ placemark.addContent(new Element("styleUrl", ns).addContent(color.getColor())); //NON-NLS
+ placemark.addContent(new Element("description", ns).addContent(description)); //NON-NLS
+ if (timestamp != null) {
+ Element time = new Element("TimeStamp", ns); //NON-NLS
+ time.addContent(new Element("when", ns).addContent(getTimeStamp(timestamp))); //NON-NLS
+ placemark.addContent(time);
+ }
+ placemark.addContent(feature);
+ if (coordinates != null && !coordinates.isEmpty()) {
+ placemark.addContent(new Element("snippet", ns).addContent(coordinates)); //NON-NLS
+ }
+ return placemark;
+ }
+
+ /**
+ * Make a Placemark for use in displaying features. Takes a
+ * coordinate-bearing feature (Point, LineString, etc) and places it in the
+ * Placemark element.
+ *
+ * @param name Placemark name
+ * @param color Placemark color
+ * @param description Description for the info bubble on the map
+ * @param timestamp Placemark timestamp
+ * @param feature The feature to show. Could be Point, LineString, etc.
+ * @param path The path to the file on disk
+ * @param coordinates The coordinates to display in the list view snippet
+ *
+ * @return the entire KML Placemark, including a picture.
+ */
+ private Element makePlacemarkWithPicture(String name, FeatureColor color, String description, Long timestamp, Element feature, Path path, String coordinates) {
+ Element placemark = new Element("Placemark", ns); //NON-NLS
+ if (name != null && !name.isEmpty()) {
+ placemark.addContent(new Element("name", ns).addContent(name)); //NON-NLS
+ }
+
+ placemark.addContent(new Element("styleUrl", ns).addContent(color.getColor())); //NON-NLS
+ Element desc = new Element("description", ns); //NON-NLS
+
+ if (path != null) {
+ String pathAsString = path.toString();
+ if (pathAsString != null && !pathAsString.isEmpty()) {
+ String image = "
"; //NON-NLS
+ desc.addContent(image);
+ }
+ }
+
+ desc.addContent(description + "File Path: " + path.toString());
+ placemark.addContent(desc);
+ if (timestamp != null) {
+ Element time = new Element("TimeStamp", ns); //NON-NLS
+ time.addContent(new Element("when", ns).addContent(getTimeStamp(timestamp))); //NON-NLS
+ placemark.addContent(time);
+ }
+ placemark.addContent(feature);
+ if (coordinates != null && !coordinates.isEmpty()) {
+ placemark.addContent(new Element("snippet", ns).addContent(coordinates)); //NON-NLS
+ }
+ return placemark;
+ }
+
+ /**
+ * Extracts the file to the output folder.
+ *
+ * @param inputFile The input AbstractFile to copy
+ * @param outputFile the output file
+ *
+ * @throws IOException
+ */
+ private void copyFileUsingStream(AbstractFile inputFile, File outputFile) throws IOException {
+ byte[] buffer = new byte[65536];
+ int length;
+ outputFile.createNewFile();
+ try (InputStream is = new ReadContentInputStream(inputFile);
+ OutputStream os = new FileOutputStream(outputFile)) {
while ((length = is.read(buffer)) != -1) {
os.write(buffer, 0, length);
}
-
- } finally {
- is.close();
- os.close();
}
}
diff --git a/Core/src/org/sleuthkit/autopsy/report/stylesheets/style.kml b/Core/src/org/sleuthkit/autopsy/report/stylesheets/style.kml
new file mode 100755
index 0000000000..aeb3992df1
--- /dev/null
+++ b/Core/src/org/sleuthkit/autopsy/report/stylesheets/style.kml
@@ -0,0 +1,299 @@
+
+
+
+
+
+ normal
+ #n_YellowPushpin
+
+
+ highlight
+ #h_YellowPushpin
+
+
+
+
+
+
+ normal
+ #n_bluePushpin
+
+
+ highlight
+ #h_bluePushpin
+
+
+
+
+
+
+ normal
+ #n_redPushpin
+
+
+ highlight
+ #h_redPushpin
+
+
+
+
+
+
+ normal
+ #n_greenPushpin
+
+
+ highlight
+ #h_greenPushpin
+
+
+
+
+
+
+ normal
+ #n_purplePushpin
+
+
+ highlight
+ #h_purplePushpin
+
+
+
+
+
+
+ normal
+ #n_whitePushpin
+
+
+ highlight
+ #h_whitePushpin
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form
index ea5a68ccdc..a05e7505ec 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form
+++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.form
@@ -54,7 +54,7 @@
-
+
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java
index 2c97d775f4..1ca594fa14 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/TimeLineTopComponent.java
@@ -61,7 +61,7 @@ import org.sleuthkit.autopsy.timeline.explorernodes.EventRootNode;
import org.sleuthkit.autopsy.timeline.ui.HistoryToolBar;
import org.sleuthkit.autopsy.timeline.ui.StatusBar;
import org.sleuthkit.autopsy.timeline.ui.TimeZonePanel;
-import org.sleuthkit.autopsy.timeline.ui.VisualizationPanel;
+import org.sleuthkit.autopsy.timeline.ui.ViewFrame;
import org.sleuthkit.autopsy.timeline.ui.detailview.tree.EventsTree;
import org.sleuthkit.autopsy.timeline.ui.filtering.FilterSetPanel;
import org.sleuthkit.autopsy.timeline.zooming.ZoomSettingsPane;
@@ -137,7 +137,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
LOGGER.log(Level.SEVERE, "Failed to lookup Sleuthkit object backing a SingleEvent.", ex); // NON-NLS
Platform.runLater(() -> {
Notifications.create()
- .owner(jFXVizPanel.getScene().getWindow())
+ .owner(jFXViewPanel.getScene().getWindow())
.text(Bundle.TimelineTopComponent_selectedEventListener_errorMsg())
.showError();
});
@@ -260,8 +260,8 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
final VBox leftVBox = new VBox(5, timeZonePanel, historyToolBar, zoomSettingsPane, leftTabPane);
SplitPane.setResizableWithParent(leftVBox, Boolean.FALSE);
- final VisualizationPanel visualizationPanel = new VisualizationPanel(controller, eventsTree);
- final SplitPane mainSplitPane = new SplitPane(leftVBox, visualizationPanel);
+ final ViewFrame viewFrame = new ViewFrame(controller, eventsTree);
+ final SplitPane mainSplitPane = new SplitPane(leftVBox, viewFrame);
mainSplitPane.setDividerPositions(0);
final Scene scene = new Scene(mainSplitPane);
@@ -278,7 +278,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
});
//add ui componenets to JFXPanels
- jFXVizPanel.setScene(scene);
+ jFXViewPanel.setScene(scene);
jFXstatusPanel.setScene(new Scene(new StatusBar(controller)));
}
@@ -297,7 +297,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
jFXstatusPanel = new javafx.embed.swing.JFXPanel();
splitYPane = new javax.swing.JSplitPane();
- jFXVizPanel = new javafx.embed.swing.JFXPanel();
+ jFXViewPanel = new javafx.embed.swing.JFXPanel();
horizontalSplitPane = new javax.swing.JSplitPane();
leftFillerPanel = new javax.swing.JPanel();
rightfillerPanel = new javax.swing.JPanel();
@@ -308,7 +308,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
splitYPane.setOrientation(javax.swing.JSplitPane.VERTICAL_SPLIT);
splitYPane.setResizeWeight(0.9);
splitYPane.setPreferredSize(new java.awt.Dimension(1024, 400));
- splitYPane.setLeftComponent(jFXVizPanel);
+ splitYPane.setLeftComponent(jFXViewPanel);
horizontalSplitPane.setDividerLocation(600);
horizontalSplitPane.setResizeWeight(0.5);
@@ -361,7 +361,7 @@ public final class TimeLineTopComponent extends TopComponent implements Explorer
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JSplitPane horizontalSplitPane;
- private javafx.embed.swing.JFXPanel jFXVizPanel;
+ private javafx.embed.swing.JFXPanel jFXViewPanel;
private javafx.embed.swing.JFXPanel jFXstatusPanel;
private javax.swing.JPanel leftFillerPanel;
private javax.swing.JPanel rightfillerPanel;
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java b/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java
index e50e1909a8..7649b35705 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/actions/SaveSnapshotAsReport.java
@@ -71,7 +71,7 @@ public class SaveSnapshotAsReport extends Action {
"Timeline.ModuleName=Timeline",
"SaveSnapShotAsReport.action.dialogs.title=Timeline",
"SaveSnapShotAsReport.action.name.text=Snapshot Report",
- "SaveSnapShotAsReport.action.longText=Save a screen capture of the visualization as a report.",
+ "SaveSnapShotAsReport.action.longText=Save a screen capture of the current view of the timeline as a report.",
"# {0} - report file path",
"SaveSnapShotAsReport.ReportSavedAt=Report saved at [{0}]",
"SaveSnapShotAsReport.Success=Success",
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/CombinedEvent.java b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/CombinedEvent.java
index 3fa3265f17..52a0488d9f 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/datamodel/CombinedEvent.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/datamodel/CombinedEvent.java
@@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.timeline.datamodel;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.Objects;
import java.util.Set;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
@@ -43,8 +44,7 @@ public class CombinedEvent {
* epoch.
* @param description The full description shared by all the combined events
* @param fileID The ID of the file all the combined events are for.
- * @param eventMap A map from EventType to the ID of the event for the
- * given file ID with that type.
+ * @param eventMap A map from EventType to event ID.
*/
public CombinedEvent(long epochMillis, String description, long fileID, Map eventMap) {
this.epochMillis = epochMillis;
@@ -105,7 +105,45 @@ public class CombinedEvent {
*
* @return An arbitrary representative event ID for the combined events.
*/
- public Long getRepresentitiveEventID() {
+ public Long getRepresentativeEventID() {
return eventTypeMap.values().stream().findFirst().get();
}
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 53 * hash + (int) (this.fileID ^ (this.fileID >>> 32));
+ hash = 53 * hash + (int) (this.epochMillis ^ (this.epochMillis >>> 32));
+ hash = 53 * hash + Objects.hashCode(this.description);
+ hash = 53 * hash + Objects.hashCode(this.eventTypeMap);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final CombinedEvent other = (CombinedEvent) obj;
+ if (this.fileID != other.fileID) {
+ return false;
+ }
+ if (this.epochMillis != other.epochMillis) {
+ return false;
+ }
+ if (!Objects.equals(this.description, other.description)) {
+ return false;
+ }
+ if (!Objects.equals(this.eventTypeMap, other.eventTypeMap)) {
+ return false;
+ }
+ return true;
+ }
+
}
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/events/RefreshRequestedEvent.java b/Core/src/org/sleuthkit/autopsy/timeline/events/RefreshRequestedEvent.java
index 47b04eb479..903cb55178 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/events/RefreshRequestedEvent.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/events/RefreshRequestedEvent.java
@@ -20,7 +20,7 @@ package org.sleuthkit.autopsy.timeline.events;
/**
* A "local" event published by filteredEventsModel to indicate that the user
- * requested that the current visualization be refreshed with out changing any
+ * requested that the current view be refreshed with out changing any
* of the parameters ( to include more up to date tag data for example.)
*
* This event is not intended for use out side of the Timeline module.
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java
index 75377ff5bb..917d2a0881 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/snapshot/SnapShotReportWriter.java
@@ -70,7 +70,7 @@ public class SnapShotReportWriter {
* @param zoomParams The ZoomParams in effect when the snapshot was
* taken.
* @param generationDate The generation Date of the report.
- * @param snapshot A snapshot of the visualization to include in the
+ * @param snapshot A snapshot of the view to include in the
* report.
*/
public SnapShotReportWriter(Case currentCase, Path reportFolderPath, String reportName, ZoomParams zoomParams, Date generationDate, BufferedImage snapshot) {
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java
index faf55aef15..86fa7ec132 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimeLineView.java
@@ -136,7 +136,7 @@ public abstract class AbstractTimeLineView extends BorderPane {
/**
* Refresh this view based on current state of zoom / filters. Primarily
- * this invokes the background VisualizationUpdateTask returned by
+ * this invokes the background ViewRefreshTask returned by
* getUpdateTask(), which derived classes must implement.
*
* TODO: replace this logic with a javafx Service ? -jm
@@ -291,11 +291,11 @@ public abstract class AbstractTimeLineView extends BorderPane {
* @throws Exception If there is an unhandled exception during the
* background operation
*/
- @NbBundle.Messages(value = {"VisualizationUpdateTask.preparing=Analyzing zoom and filter settings"})
+ @NbBundle.Messages(value = {"ViewRefreshTask.preparing=Analyzing zoom and filter settings"})
@Override
protected Boolean call() throws Exception {
updateProgress(-1, 1);
- updateMessage(Bundle.VisualizationUpdateTask_preparing());
+ updateMessage(Bundle.ViewRefreshTask_preparing());
Platform.runLater(() -> {
MaskerPane maskerPane = new MaskerPane();
maskerPane.textProperty().bind(messageProperty());
diff --git a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimelineChart.java b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimelineChart.java
index fc2ee5ca63..38f05a9bfc 100644
--- a/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimelineChart.java
+++ b/Core/src/org/sleuthkit/autopsy/timeline/ui/AbstractTimelineChart.java
@@ -57,7 +57,7 @@ import org.sleuthkit.autopsy.timeline.TimeLineController;
import org.sleuthkit.autopsy.timeline.datamodel.eventtype.EventType;
/**
- * Abstract base class for TimeLineChart based visualizations.
+ * Abstract base class for TimeLineChart based views.
*
* @param The type of data plotted along the x axis
* @param The type of data plotted along the y axis
@@ -74,12 +74,12 @@ public abstract class AbstractTimelineChart of the nodes that are selected in
- * this visualization.
+ * this view.
*/
protected ObservableList getSelectedNodes() {
return selectedNodes;
@@ -127,18 +127,18 @@ public abstract class AbstractTimelineChart getXAxis();
/**
- * Get the Y-Axis of this Visualization's chart
+ * Get the Y-Axis of this view's chart
*
- * @return The vertical axis used by this Visualization's chart
+ * @return The vertical axis used by this view's chart
*/
abstract protected Axis getYAxis();
@@ -252,7 +252,7 @@ public abstract class AbstractTimelineChart
-