mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-17 18:17:43 +00:00
Merge remote-tracking branch 'upstream/TL-list-view' into 788-lazy-context-menus
This commit is contained in:
commit
0301793d31
@ -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 {
|
||||
}// </editor-fold>//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 {
|
||||
|
@ -225,7 +225,8 @@ ReportHTML.writeSum.noCaseNum=<i>No case number</i>
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -2,7 +2,7 @@
|
||||
*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2014 Basis Technology Corp.
|
||||
* Copyright 2014-2016 Basis Technology Corp.
|
||||
* contact: carrier <at> sleuthkit <dot> 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 = "<br>";
|
||||
|
||||
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
|
||||
try {
|
||||
try (BufferedWriter out = new BufferedWriter(new FileWriter(reportPath2))) {
|
||||
ns = Namespace.getNamespace("", "http://www.opengis.net/kml/2.2"); //NON-NLS
|
||||
|
||||
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_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
|
||||
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);
|
||||
|
||||
// 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
|
||||
ReportBranding rb = new ReportBranding();
|
||||
name.setText(rb.getReportTitle() + " KML"); //NON-NLS
|
||||
document.addContent(name);
|
||||
|
||||
/*
|
||||
* Step 2: add in Style elements
|
||||
// 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.
|
||||
*
|
||||
*/
|
||||
// Style
|
||||
Element style = new Element("Style", ns); //NON-NLS
|
||||
style.setAttribute("id", "redIcon"); //NON-NLS
|
||||
document.addContent(style);
|
||||
try {
|
||||
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));
|
||||
}
|
||||
|
||||
// IconStyle
|
||||
Element iconStyle = new Element("IconStyle", ns); //NON-NLS
|
||||
style.addContent(iconStyle);
|
||||
}
|
||||
} catch (TskCoreException | IOException ex) {
|
||||
logger.log(Level.SEVERE, "Could not extract photos with EXIF metadata.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
// color
|
||||
Element color = new Element("color", ns); //NON-NLS
|
||||
color.setText("990000ff"); //NON-NLS
|
||||
iconStyle.addContent(color);
|
||||
try {
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)) {
|
||||
Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||
String desc = getDescriptionFromArtifact(artifact, "GPS Bookmark"); //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));
|
||||
String bookmarkName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
|
||||
String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
|
||||
gpsBookmarksFolder.addContent(makePlacemark(bookmarkName, FeatureColor.BLUE, desc, timestamp, point, formattedCoordinates));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not get GPS Bookmarks from database.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
// Icon
|
||||
Element icon = new Element("Icon", ns); //NON-NLS
|
||||
iconStyle.addContent(icon);
|
||||
try {
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION)) {
|
||||
Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||
String desc = getDescriptionFromArtifact(artifact, "GPS Last Known Location"); //NON-NLS
|
||||
Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
|
||||
Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
|
||||
Double alt = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
|
||||
Element point = makePoint(lat, lon, alt);
|
||||
String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
|
||||
gpsLastKnownLocationFolder.addContent(makePlacemark("Last Known Location", FeatureColor.PURPLE, desc, timestamp, point, formattedCoordinates)); //NON-NLS
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not get GPS Last Known Location from database.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) {
|
||||
Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||
String desc = getDescriptionFromArtifact(artifact, "GPS Route");
|
||||
Double latitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
|
||||
Double longitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
|
||||
Double latitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
|
||||
Double longitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
|
||||
Double altitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
|
||||
|
||||
Element route = makeLineString(latitudeStart, longitudeStart, altitude, latitudeEnd, longitudeEnd, altitude);
|
||||
Element startingPoint = makePoint(latitudeStart, longitudeStart, altitude);
|
||||
Element endingPoint = makePoint(latitudeEnd, longitudeEnd, altitude);
|
||||
|
||||
String formattedCoordinates = String.format("%.2f, %.2f to %.2f, %.2f", latitudeStart, longitudeStart, latitudeEnd, longitudeEnd);
|
||||
gpsRouteFolder.addContent(makePlacemark("As-the-crow-flies Route", FeatureColor.GREEN, desc, timestamp, route, formattedCoordinates)); //NON-NLS
|
||||
|
||||
formattedCoordinates = String.format("%.2f, %.2f", latitudeStart, longitudeStart);
|
||||
gpsRouteFolder.addContent(makePlacemark("Start", FeatureColor.GREEN, desc, timestamp, startingPoint, formattedCoordinates)); //NON-NLS
|
||||
|
||||
formattedCoordinates = String.format("%.2f, %.2f", latitudeEnd, longitudeEnd);
|
||||
gpsRouteFolder.addContent(makePlacemark("End", FeatureColor.GREEN, desc, timestamp, endingPoint, formattedCoordinates)); //NON-NLS
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not get GPS Routes from database.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH)) {
|
||||
Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||
String desc = getDescriptionFromArtifact(artifact, "GPS Search"); //NON-NLS
|
||||
Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
|
||||
Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
|
||||
Double alt = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
|
||||
Element point = makePoint(lat, lon, alt);
|
||||
String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
|
||||
String searchName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
|
||||
if (searchName == null || searchName.isEmpty()) {
|
||||
searchName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION);
|
||||
}
|
||||
if (searchName == null || searchName.isEmpty()) {
|
||||
searchName = "GPS Search";
|
||||
}
|
||||
gpsSearchesFolder.addContent(makePlacemark(searchName, FeatureColor.WHITE, desc, timestamp, point, formattedCoordinates)); //NON-NLS
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not get GPS Searches from database.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
try {
|
||||
for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) {
|
||||
Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||
String desc = getDescriptionFromArtifact(artifact, "GPS Trackpoint"); //NON-NLS
|
||||
Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
|
||||
Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
|
||||
Double alt = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
|
||||
Element point = makePoint(lat, lon, alt);
|
||||
String formattedCoordinates = String.format("%.2f, %.2f, %.2f", lat, lon, alt);
|
||||
String trackName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
|
||||
if (trackName == null || trackName.isEmpty()) {
|
||||
trackName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME);
|
||||
}
|
||||
if (trackName == null || trackName.isEmpty()) {
|
||||
trackName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG);
|
||||
}
|
||||
if (trackName == null || trackName.isEmpty()) {
|
||||
trackName = "GPS Trackpoint";
|
||||
}
|
||||
gpsTrackpointsFolder.addContent(makePlacemark(trackName, FeatureColor.YELLOW, desc, timestamp, point, formattedCoordinates));
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Could not get GPS Trackpoints from database.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
// 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 = "<![CDATA[ \n" + " <img src='file:///" + savedPath + "' width='400' /><br/> \n"; //NON-NLS
|
||||
StringEscapeUtils.unescapeXml(xml);
|
||||
pmDescription.setText(xml);
|
||||
placemark.addContent(pmDescription);
|
||||
}
|
||||
}
|
||||
|
||||
// styleUrl
|
||||
Element pmStyleUrl = new Element("styleUrl", ns); //NON-NLS
|
||||
pmStyleUrl.setText("#redIcon"); //NON-NLS
|
||||
placemark.addContent(pmStyleUrl);
|
||||
|
||||
// Point
|
||||
Element pmPoint = new Element("Point", ns); //NON-NLS
|
||||
placemark.addContent(pmPoint);
|
||||
|
||||
// coordinates
|
||||
Element pmCoordinates = new Element("coordinates", ns); //NON-NLS
|
||||
|
||||
pmCoordinates.setText(coordinates);
|
||||
pmPoint.addContent(pmCoordinates);
|
||||
|
||||
}
|
||||
|
||||
// read the next line
|
||||
line = reader.readLine();
|
||||
}
|
||||
|
||||
}
|
||||
progressPanel.increment();
|
||||
/*
|
||||
* Step 4: write the XML file
|
||||
*/
|
||||
try (FileOutputStream writer = new FileOutputStream(reportPath)) {
|
||||
try (FileOutputStream writer = new FileOutputStream(kmlFileFullPath)) {
|
||||
XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
|
||||
outputter.output(kmlDocument, writer);
|
||||
Case.getCurrentCase().addReport(reportPath, NbBundle.getMessage(this.getClass(),
|
||||
"ReportKML.genReport.srcModuleName.text"), "");
|
||||
Case.getCurrentCase().addReport(kmlFileFullPath,
|
||||
NbBundle.getMessage(this.getClass(), "ReportKML.genReport.srcModuleName.text"),
|
||||
NbBundle.getMessage(this.getClass(), "ReportKML.genReport.reportName"));
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could not write the KML file.", ex); //NON-NLS
|
||||
} catch (TskCoreException ex) {
|
||||
String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
|
||||
logger.log(Level.SEVERE, errorMessage, ex);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.WARNING, "Could not write the KML report.", ex); //NON-NLS
|
||||
}
|
||||
logger.log(Level.SEVERE, "Could not write the KML file.", ex); //NON-NLS
|
||||
progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR);
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.WARNING, "Failed to get the unique path.", ex); //NON-NLS
|
||||
String errorMessage = String.format("Error adding %s to case as a report", kmlFileFullPath); //NON-NLS
|
||||
logger.log(Level.SEVERE, errorMessage, ex);
|
||||
progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR);
|
||||
}
|
||||
|
||||
// Copy the style sheet
|
||||
try {
|
||||
InputStream input = getClass().getResourceAsStream(STYLESHEETS_PATH + KML_STYLE_FILE); // Preserve slash direction
|
||||
OutputStream output = new FileOutputStream(baseReportDir + KML_STYLE_FILE); // Preserve slash direction
|
||||
FileUtil.copy(input, output);
|
||||
} catch (IOException ex) {
|
||||
logger.log(Level.SEVERE, "Error placing KML stylesheet. The .KML file will not function properly.", ex); //NON-NLS
|
||||
}
|
||||
|
||||
progressPanel.increment();
|
||||
progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE);
|
||||
}
|
||||
|
||||
public static void copyFileUsingStream(AbstractFile file, File jFile) throws IOException {
|
||||
InputStream is = new ReadContentInputStream(file);
|
||||
OutputStream os = new FileOutputStream(jFile);
|
||||
byte[] buffer = new byte[8192];
|
||||
int length;
|
||||
/**
|
||||
* Get a Double from an artifact if it exists, return null otherwise.
|
||||
*
|
||||
* @param artifact The artifact to query
|
||||
* @param type The attribute type we're looking for
|
||||
*
|
||||
* @return The Double if it exists, or null if not
|
||||
*/
|
||||
private Double getDouble(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
|
||||
Double returnValue = null;
|
||||
try {
|
||||
BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
|
||||
if (bba != null) {
|
||||
Double value = bba.getValueDouble();
|
||||
if (value != null) {
|
||||
returnValue = value;
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting Double value: " + type.toString(), ex); //NON-NLS
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Long from an artifact if it exists, return null otherwise.
|
||||
*
|
||||
* @param artifact The artifact to query
|
||||
* @param type The attribute type we're looking for
|
||||
*
|
||||
* @return The Long if it exists, or null if not
|
||||
*/
|
||||
private Long getLong(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
|
||||
Long returnValue = null;
|
||||
try {
|
||||
BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
|
||||
if (bba != null) {
|
||||
Long value = bba.getValueLong();
|
||||
if (value != null) {
|
||||
returnValue = value;
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting Long value: " + type.toString(), ex); //NON-NLS
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an Integer from an artifact if it exists, return null otherwise.
|
||||
*
|
||||
* @param artifact The artifact to query
|
||||
* @param type The attribute type we're looking for
|
||||
*
|
||||
* @return The Integer if it exists, or null if not
|
||||
*/
|
||||
private Integer getInteger(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
|
||||
Integer returnValue = null;
|
||||
try {
|
||||
BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
|
||||
if (bba != null) {
|
||||
Integer value = bba.getValueInt();
|
||||
if (value != null) {
|
||||
returnValue = value;
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting Integer value: " + type.toString(), ex); //NON-NLS
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a String from an artifact if it exists, return null otherwise.
|
||||
*
|
||||
* @param artifact The artifact to query
|
||||
* @param type The attribute type we're looking for
|
||||
*
|
||||
* @return The String if it exists, or null if not
|
||||
*/
|
||||
private String getString(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
|
||||
String returnValue = null;
|
||||
try {
|
||||
BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
|
||||
if (bba != null) {
|
||||
String value = bba.getValueString();
|
||||
if (value != null && !value.isEmpty()) {
|
||||
returnValue = value;
|
||||
}
|
||||
}
|
||||
} catch (TskCoreException ex) {
|
||||
logger.log(Level.SEVERE, "Error getting String value: " + type.toString(), ex); //NON-NLS
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method creates a text description for a map feature using all the
|
||||
* geospatial and time data we can for the Artifact. It queries the
|
||||
* following attributes:
|
||||
*
|
||||
* TSK_GEO_LATITUDE 54; TSK_GEO_LONGITUDE 55; TSK_GEO_LATITUDE_START 98;
|
||||
* TSK_GEO_LATITUDE_END 99; TSK_GEO_LONGITUDE_START 100;
|
||||
* TSK_GEO_LONGITUDE_END 101; TSK_GEO_VELOCITY 56; TSK_GEO_ALTITUDE 57;
|
||||
* TSK_GEO_BEARING 58; TSK_GEO_HPRECISION 59; TSK_GEO_VPRECISION 60;
|
||||
* TSK_GEO_MAPDATUM 61; TSK_DATETIME_START 83; TSK_DATETIME_END 84;
|
||||
* TSK_LOCATION 86; TSK_PATH_SOURCE 94;
|
||||
*
|
||||
* @param artifact the artifact to query.
|
||||
* @param featureType the type of Artifact we're working on.
|
||||
*
|
||||
* @return a String with the information we have available
|
||||
*/
|
||||
private String getDescriptionFromArtifact(BlackboardArtifact artifact, String featureType) {
|
||||
StringBuilder result = new StringBuilder("<h3>" + featureType + "</h3>"); //NON-NLS
|
||||
|
||||
String name = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
|
||||
if (name != null && !name.isEmpty()) {
|
||||
result.append("<b>Name:</b> ").append(name).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String location = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION);
|
||||
if (location != null && !location.isEmpty()) {
|
||||
result.append("<b>Location:</b> ").append(location).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
|
||||
if (timestamp != null) {
|
||||
result.append("<b>Timestamp:</b> ").append(getTimeStamp(timestamp)).append(SEP); //NON-NLS
|
||||
result.append("<b>Unix timestamp:</b> ").append(timestamp).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Long startingTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START);
|
||||
if (startingTimestamp != null) {
|
||||
result.append("<b>Starting Timestamp:</b> ").append(getTimeStamp(startingTimestamp)).append(SEP); //NON-NLS
|
||||
result.append("<b>Starting Unix timestamp:</b> ").append(startingTimestamp).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Long endingTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END);
|
||||
if (endingTimestamp != null) {
|
||||
result.append("<b>Ending Timestamp:</b> ").append(getTimeStamp(endingTimestamp)).append(SEP); //NON-NLS
|
||||
result.append("<b>Ending Unix timestamp:</b> ").append(endingTimestamp).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Long createdTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED);
|
||||
if (createdTimestamp != null) {
|
||||
result.append("<b>Created Timestamp:</b> ").append(getTimeStamp(createdTimestamp)).append(SEP); //NON-NLS
|
||||
result.append("<b>Created Unix timestamp:</b> ").append(createdTimestamp).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double latitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
|
||||
if (latitude != null) {
|
||||
result.append("<b>Latitude:</b> ").append(latitude).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double longitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
|
||||
if (longitude != null) {
|
||||
result.append("<b>Longitude:</b> ").append(longitude).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double latitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
|
||||
if (latitudeStart != null) {
|
||||
result.append("<b>Latitude Start:</b> ").append(latitudeStart).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double longitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
|
||||
if (longitudeStart != null) {
|
||||
result.append("<b>Longitude Start:</b> ").append(longitudeStart).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double latitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
|
||||
if (latitudeEnd != null) {
|
||||
result.append("<b>Latitude End:</b> ").append(latitudeEnd).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double longitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
|
||||
if (longitudeEnd != null) {
|
||||
result.append("<b>Longitude End:</b> ").append(longitudeEnd).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double velocity = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_VELOCITY);
|
||||
if (velocity != null) {
|
||||
result.append("<b>Velocity:</b> ").append(velocity).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double altitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
|
||||
if (altitude != null) {
|
||||
result.append("<b>Altitude:</b> ").append(altitude).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Double bearing = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_BEARING);
|
||||
if (bearing != null) {
|
||||
result.append("<b>Bearing:</b> ").append(bearing).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Integer hPrecision = getInteger(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_HPRECISION);
|
||||
if (hPrecision != null) {
|
||||
result.append("<b>Horizontal Precision Figure of Merit:</b> ").append(hPrecision).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
Integer vPrecision = getInteger(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_VPRECISION);
|
||||
if (vPrecision != null) {
|
||||
result.append("<b>Vertical Precision Figure of Merit:</b> ").append(vPrecision).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String mapDatum = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_MAPDATUM);
|
||||
if (mapDatum != null && !mapDatum.isEmpty()) {
|
||||
result.append("<b>Map Datum:</b> ").append(mapDatum).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String programName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME);
|
||||
if (programName != null && !programName.isEmpty()) {
|
||||
result.append("<b>Reported by:</b> ").append(programName).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String flag = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG);
|
||||
if (flag != null && !flag.isEmpty()) {
|
||||
result.append("<b>Flag:</b> ").append(flag).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String pathSource = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_SOURCE);
|
||||
if (pathSource != null && !pathSource.isEmpty()) {
|
||||
result.append("<b>Source:</b> ").append(pathSource).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String deviceMake = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE);
|
||||
if (deviceMake != null && !deviceMake.isEmpty()) {
|
||||
result.append("<b>Device Make:</b> ").append(deviceMake).append(SEP); //NON-NLS
|
||||
}
|
||||
|
||||
String deviceModel = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
|
||||
if (deviceModel != null && !deviceModel.isEmpty()) {
|
||||
result.append("<b>Device Model:</b> ").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 = "<img src='file:///" + pathAsString + "' width='400'/>"; //NON-NLS
|
||||
desc.addContent(image);
|
||||
}
|
||||
}
|
||||
|
||||
desc.addContent(description + "<b>File Path:</b> " + 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();
|
||||
}
|
||||
}
|
||||
|
||||
|
299
Core/src/org/sleuthkit/autopsy/report/stylesheets/style.kml
Executable file
299
Core/src/org/sleuthkit/autopsy/report/stylesheets/style.kml
Executable file
@ -0,0 +1,299 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gx="http://www.google.com/kml/ext/2.2" xmlns:kml="http://www.opengis.net/kml/2.2">
|
||||
<Document>
|
||||
<StyleMap id="yellowFeature">
|
||||
<Pair>
|
||||
<key>normal</key>
|
||||
<styleUrl>#n_YellowPushpin</styleUrl>
|
||||
</Pair>
|
||||
<Pair>
|
||||
<key>highlight</key>
|
||||
<styleUrl>#h_YellowPushpin</styleUrl>
|
||||
</Pair>
|
||||
</StyleMap>
|
||||
<Style id="n_YellowPushpin">
|
||||
<IconStyle>
|
||||
<scale>1.0</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>0</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FF00FFFF</color>
|
||||
<width>5.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<Style id="h_YellowPushpin">
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/ylw-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FF00FFFF</color>
|
||||
<width>10.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<StyleMap id="blueFeature">
|
||||
<Pair>
|
||||
<key>normal</key>
|
||||
<styleUrl>#n_bluePushpin</styleUrl>
|
||||
</Pair>
|
||||
<Pair>
|
||||
<key>highlight</key>
|
||||
<styleUrl>#h_bluePushpin</styleUrl>
|
||||
</Pair>
|
||||
</StyleMap>
|
||||
<Style id="n_bluePushpin">
|
||||
<IconStyle>
|
||||
<scale>1.0</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>0</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FFE63900</color>
|
||||
<width>5.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<Style id="h_bluePushpin">
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/blue-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FFE63900</color>
|
||||
<width>10.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<StyleMap id="redFeature">
|
||||
<Pair>
|
||||
<key>normal</key>
|
||||
<styleUrl>#n_redPushpin</styleUrl>
|
||||
</Pair>
|
||||
<Pair>
|
||||
<key>highlight</key>
|
||||
<styleUrl>#h_redPushpin</styleUrl>
|
||||
</Pair>
|
||||
</StyleMap>
|
||||
<Style id="n_redPushpin">
|
||||
<IconStyle>
|
||||
<scale>1.0</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>0</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FF0000FF</color>
|
||||
<width>5.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<Style id="h_redPushpin">
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/red-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FF0000FF</color>
|
||||
<width>10.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<StyleMap id="greenFeature">
|
||||
<Pair>
|
||||
<key>normal</key>
|
||||
<styleUrl>#n_greenPushpin</styleUrl>
|
||||
</Pair>
|
||||
<Pair>
|
||||
<key>highlight</key>
|
||||
<styleUrl>#h_greenPushpin</styleUrl>
|
||||
</Pair>
|
||||
</StyleMap>
|
||||
<Style id="n_greenPushpin">
|
||||
<IconStyle>
|
||||
<scale>1.0</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FF00CC00</color>
|
||||
<width>5.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>
|
||||
A route was planned between these two points. The green line connecting the points is not the actual route, but it indicates which Start and End points are associated with each other.
|
||||
$[description]
|
||||
</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<Style id="h_greenPushpin">
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/grn-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FF00CC00</color>
|
||||
<width>10.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>
|
||||
A route was planned between these two points. The green line connecting the points is not the actual route, but it indicates which Start and End points are associated with each other.
|
||||
$[description]
|
||||
</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<StyleMap id="purpleFeature">
|
||||
<Pair>
|
||||
<key>normal</key>
|
||||
<styleUrl>#n_purplePushpin</styleUrl>
|
||||
</Pair>
|
||||
<Pair>
|
||||
<key>highlight</key>
|
||||
<styleUrl>#h_purplePushpin</styleUrl>
|
||||
</Pair>
|
||||
</StyleMap>
|
||||
<Style id="n_purplePushpin">
|
||||
<IconStyle>
|
||||
<scale>1.0</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/purple-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FFCC0066</color>
|
||||
<width>5.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<Style id="h_purplePushpin">
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/purple-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FFCC0066</color>
|
||||
<width>10.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
<StyleMap id="whiteFeature">
|
||||
<Pair>
|
||||
<key>normal</key>
|
||||
<styleUrl>#n_whitePushpin</styleUrl>
|
||||
</Pair>
|
||||
<Pair>
|
||||
<key>highlight</key>
|
||||
<styleUrl>#h_whitePushpin</styleUrl>
|
||||
</Pair>
|
||||
</StyleMap>
|
||||
<Style id="n_whitePushpin">
|
||||
<IconStyle>
|
||||
<scale>1.0</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>0</scale>
|
||||
</LabelStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
<LineStyle>
|
||||
<color>FFFFFFFF</color>
|
||||
<width>5.0</width>
|
||||
</LineStyle>
|
||||
</Style>
|
||||
<Style id="h_whitePushpin">
|
||||
<IconStyle>
|
||||
<scale>1.3</scale>
|
||||
<Icon>
|
||||
<href>http://maps.google.com/mapfiles/kml/pushpin/wht-pushpin.png</href>
|
||||
</Icon>
|
||||
<hotSpot x="20" y="2" xunits="pixels" yunits="pixels" />
|
||||
</IconStyle>
|
||||
<LabelStyle>
|
||||
<scale>1</scale>
|
||||
</LabelStyle>
|
||||
<LineStyle>
|
||||
<color>FFFFFFFF</color>
|
||||
<width>10.0</width>
|
||||
</LineStyle>
|
||||
<BalloonStyle>
|
||||
<text>$[description]</text>
|
||||
</BalloonStyle>
|
||||
</Style>
|
||||
</Document>
|
||||
</kml>
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2011-2015 Basis Technology Corp.
|
||||
* Copyright 2011-2016 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> org
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@ -45,6 +45,13 @@ import org.openide.util.NbBundle;
|
||||
import org.sleuthkit.autopsy.corecomponents.OptionsPanel;
|
||||
import org.sleuthkit.autopsy.coreutils.Logger;
|
||||
import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
import java.awt.Component;
|
||||
import javax.swing.ImageIcon;
|
||||
import javax.swing.JLabel;
|
||||
import static javax.swing.SwingConstants.CENTER;
|
||||
import javax.swing.table.DefaultTableCellRenderer;
|
||||
import javax.swing.table.TableCellRenderer;
|
||||
import org.openide.util.NbBundle.Messages;
|
||||
|
||||
/**
|
||||
* GlobalEditListPanel widget to manage keywords in lists
|
||||
@ -52,7 +59,8 @@ import org.sleuthkit.autopsy.ingest.IngestManager;
|
||||
class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionListener, OptionsPanel {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(GlobalEditListPanel.class.getName());
|
||||
private KeywordTableModel tableModel;
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final KeywordTableModel tableModel;
|
||||
private KeywordList currentKeywordList;
|
||||
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
|
||||
|
||||
@ -85,7 +93,8 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
||||
column.setPreferredWidth(((int) (width * 0.90)));
|
||||
} else {
|
||||
column.setPreferredWidth(((int) (width * 0.10)));
|
||||
//column.setCellRenderer(new CheckBoxRenderer());
|
||||
column.setCellRenderer(new CheckBoxRenderer());
|
||||
column.setHeaderRenderer(new HeaderRenderer(keywordTable));
|
||||
}
|
||||
}
|
||||
keywordTable.setCellSelectionEnabled(false);
|
||||
@ -686,4 +695,55 @@ class GlobalEditListPanel extends javax.swing.JPanel implements ListSelectionLis
|
||||
resync();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A cell renderer for boolean cells that shows a center-aligned green check
|
||||
* mark if true, nothing if false.
|
||||
*/
|
||||
private class CheckBoxRenderer extends DefaultTableCellRenderer {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
final ImageIcon theCheck = new javax.swing.ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/keywordsearch/checkmark.png")); // NON-NLS
|
||||
|
||||
CheckBoxRenderer() {
|
||||
setHorizontalAlignment(CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Messages("IsRegularExpression=Keyword is a regular expression")
|
||||
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
|
||||
|
||||
if ((value instanceof Boolean)) {
|
||||
if ((Boolean) value) {
|
||||
setIcon(theCheck);
|
||||
setToolTipText(Bundle.IsRegularExpression());
|
||||
} else {
|
||||
setIcon(null);
|
||||
setToolTipText(null);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A cell renderer for header cells that center-aligns the header text.
|
||||
*/
|
||||
private static class HeaderRenderer implements TableCellRenderer {
|
||||
|
||||
private DefaultTableCellRenderer renderer;
|
||||
|
||||
public HeaderRenderer(JTable table) {
|
||||
renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
|
||||
renderer.setHorizontalAlignment(JLabel.CENTER);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getTableCellRendererComponent(
|
||||
JTable table, Object value, boolean isSelected,
|
||||
boolean hasFocus, int row, int col) {
|
||||
return renderer.getTableCellRendererComponent(
|
||||
table, value, isSelected, hasFocus, row, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/checkmark.png
Executable file
BIN
KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/checkmark.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 279 B |
Loading…
x
Reference in New Issue
Block a user