Autopsy  4.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ReportKML.java
Go to the documentation of this file.
1 /*
2  *
3  * Autopsy Forensic Browser
4  *
5  * Copyright 2014-2016 Basis Technology Corp.
6  * contact: carrier <at> sleuthkit <dot> org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 package org.sleuthkit.autopsy.report;
21 
22 import javax.swing.JPanel;
23 
24 import org.openide.util.NbBundle;
27 import org.sleuthkit.datamodel.*;
30 import java.io.File;
31 import java.io.FileOutputStream;
32 import java.io.IOException;
33 import java.io.InputStream;
34 import java.io.OutputStream;
35 import java.nio.file.Path;
36 import java.nio.file.Paths;
37 import java.text.SimpleDateFormat;
38 import java.util.logging.Level;
39 import org.jdom2.Document;
40 import org.jdom2.Element;
41 import org.jdom2.Namespace;
42 import org.jdom2.output.Format;
43 import org.jdom2.output.XMLOutputter;
44 import org.jdom2.CDATA;
45 import org.openide.filesystems.FileUtil;
46 
50 class ReportKML implements GeneralReportModule {
51 
52  private static final Logger logger = Logger.getLogger(ReportKML.class.getName());
53  private static final String KML_STYLE_FILE = "style.kml";
54  private static final String REPORT_KML = "ReportKML.kml";
55  private static final String STYLESHEETS_PATH = "/org/sleuthkit/autopsy/report/stylesheets/";
56  private static ReportKML instance = null;
57  private Case currentCase;
58  private SleuthkitCase skCase;
59  private final SimpleDateFormat kmlDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
60  private Namespace ns;
61  private final String SEP = "<br>";
62 
63  private enum FeatureColor {
64  RED("style.kml#redFeature"),
65  GREEN("style.kml#greenFeature"),
66  BLUE("style.kml#blueFeature"),
67  PURPLE("style.kml#purpleFeature"),
68  WHITE("style.kml#whiteFeature"),
69  YELLOW("style.kml#yellowFeature");
70  private String color;
71 
72  FeatureColor(String color) {
73  this.color = color;
74  }
75 
76  String getColor() {
77  return this.color;
78  }
79  }
80 
81  // Hidden constructor for the report
82  private ReportKML() {
83  }
84 
85  // Get the default implementation of this report
86  public static synchronized ReportKML getDefault() {
87  if (instance == null) {
88  instance = new ReportKML();
89  }
90  return instance;
91  }
92 
99  @Override
100  public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
101 
102  // Start the progress bar and setup the report
103  progressPanel.setIndeterminate(true);
104  progressPanel.start();
105  progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying"));
106  String kmlFileFullPath = baseReportDir + REPORT_KML; //NON-NLS
107  currentCase = Case.getCurrentCase();
108  skCase = currentCase.getSleuthkitCase();
109 
110  progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.loading"));
111 
112  ns = Namespace.getNamespace("", "http://www.opengis.net/kml/2.2"); //NON-NLS
113 
114  Element kml = new Element("kml", ns); //NON-NLS
115  kml.addNamespaceDeclaration(Namespace.getNamespace("gx", "http://www.google.com/kml/ext/2.2")); //NON-NLS
116  kml.addNamespaceDeclaration(Namespace.getNamespace("kml", "http://www.opengis.net/kml/2.2")); //NON-NLS
117  kml.addNamespaceDeclaration(Namespace.getNamespace("atom", "http://www.w3.org/2005/Atom")); //NON-NLS
118  Document kmlDocument = new Document(kml);
119 
120  Element document = new Element("Document", ns); //NON-NLS
121  kml.addContent(document);
122 
123  Element name = new Element("name", ns); //NON-NLS
124  ReportBranding rb = new ReportBranding();
125  name.setText(rb.getReportTitle() + " KML"); //NON-NLS
126  document.addContent(name);
127 
128  // Check if ingest has finished
129  if (IngestManager.getInstance().isIngestRunning()) {
130  Element ingestwarning = new Element("snippet", ns); //NON-NLS
131  ingestwarning.addContent(NbBundle.getMessage(this.getClass(), "ReportBodyFile.ingestWarning.text")); //NON-NLS
132  document.addContent(ingestwarning);
133  }
134 
135  // Create folder structure
136  Element gpsExifMetadataFolder = new Element("Folder", ns); //NON-NLS
137  CDATA cdataExifMetadataFolder = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/camera-icon-16.png"); //NON-NLS
138  Element hrefExifMetadata = new Element("href", ns).addContent(cdataExifMetadataFolder); //NON-NLS
139  gpsExifMetadataFolder.addContent(new Element("Icon", ns).addContent(hrefExifMetadata)); //NON-NLS
140 
141  Element gpsBookmarksFolder = new Element("Folder", ns); //NON-NLS
142  CDATA cdataBookmarks = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gpsfav.png"); //NON-NLS
143  Element hrefBookmarks = new Element("href", ns).addContent(cdataBookmarks); //NON-NLS
144  gpsBookmarksFolder.addContent(new Element("Icon", ns).addContent(hrefBookmarks)); //NON-NLS
145 
146  Element gpsLastKnownLocationFolder = new Element("Folder", ns); //NON-NLS
147  CDATA cdataLastKnownLocation = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-lastlocation.png"); //NON-NLS
148  Element hrefLastKnownLocation = new Element("href", ns).addContent(cdataLastKnownLocation); //NON-NLS
149  gpsLastKnownLocationFolder.addContent(new Element("Icon", ns).addContent(hrefLastKnownLocation)); //NON-NLS
150 
151  Element gpsRouteFolder = new Element("Folder", ns); //NON-NLS
152  CDATA cdataRoute = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-trackpoint.png"); //NON-NLS
153  Element hrefRoute = new Element("href", ns).addContent(cdataRoute); //NON-NLS
154  gpsRouteFolder.addContent(new Element("Icon", ns).addContent(hrefRoute)); //NON-NLS
155 
156  Element gpsSearchesFolder = new Element("Folder", ns); //NON-NLS
157  CDATA cdataSearches = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-search.png"); //NON-NLS
158  Element hrefSearches = new Element("href", ns).addContent(cdataSearches); //NON-NLS
159  gpsSearchesFolder.addContent(new Element("Icon", ns).addContent(hrefSearches)); //NON-NLS
160 
161  Element gpsTrackpointsFolder = new Element("Folder", ns); //NON-NLS
162  CDATA cdataTrackpoints = new CDATA("https://raw.githubusercontent.com/sleuthkit/autopsy/develop/Core/src/org/sleuthkit/autopsy/images/gps-trackpoint.png"); //NON-NLS
163  Element hrefTrackpoints = new Element("href", ns).addContent(cdataTrackpoints); //NON-NLS
164  gpsTrackpointsFolder.addContent(new Element("Icon", ns).addContent(hrefTrackpoints)); //NON-NLS
165 
166  gpsExifMetadataFolder.addContent(new Element("name", ns).addContent("EXIF Metadata")); //NON-NLS
167  gpsBookmarksFolder.addContent(new Element("name", ns).addContent("GPS Bookmarks")); //NON-NLS
168  gpsLastKnownLocationFolder.addContent(new Element("name", ns).addContent("GPS Last Known Location")); //NON-NLS
169  gpsRouteFolder.addContent(new Element("name", ns).addContent("GPS Routes")); //NON-NLS
170  gpsSearchesFolder.addContent(new Element("name", ns).addContent("GPS Searches")); //NON-NLS
171  gpsTrackpointsFolder.addContent(new Element("name", ns).addContent("GPS Trackpoints")); //NON-NLS
172 
173  document.addContent(gpsExifMetadataFolder);
174  document.addContent(gpsBookmarksFolder);
175  document.addContent(gpsLastKnownLocationFolder);
176  document.addContent(gpsRouteFolder);
177  document.addContent(gpsSearchesFolder);
178  document.addContent(gpsTrackpointsFolder);
179 
180  ReportProgressPanel.ReportStatus result = ReportProgressPanel.ReportStatus.COMPLETE;
181 
197  try {
199  try {
200  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED);
201  String desc = getDescriptionFromArtifact(artifact, "EXIF Metadata With Locations"); //NON-NLS
202  Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
203  Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
204  Element point = makePoint(lat, lon, getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE));
205 
206  if (lat != null && lat != 0.0 && lon != null && lon != 0.0) {
207  AbstractFile abstractFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
208  Path path = null;
209  copyFileUsingStream(abstractFile, Paths.get(baseReportDir, abstractFile.getName()).toFile());
210  try {
211  path = Paths.get(removeLeadingImgAndVol(abstractFile.getUniquePath()));
212  } catch (TskCoreException ex) {
213  path = Paths.get(abstractFile.getParentPath(), abstractFile.getName());
214  }
215  String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
216  if (path == null) {
217  path = Paths.get(abstractFile.getName());
218  }
219  gpsExifMetadataFolder.addContent(makePlacemarkWithPicture(abstractFile.getName(), FeatureColor.RED, desc, timestamp, point, path, formattedCoordinates));
220  }
221  } catch (Exception ex) {
222  logger.log(Level.SEVERE, "Could not extract photo information.", ex); //NON-NLS
223  result = ReportProgressPanel.ReportStatus.ERROR;
224  }
225  }
226  } catch (TskCoreException ex) {
227  logger.log(Level.SEVERE, "Could not extract photos with EXIF metadata.", ex); //NON-NLS
228  result = ReportProgressPanel.ReportStatus.ERROR;
229  }
230 
231  try {
233  try {
234  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
235  String desc = getDescriptionFromArtifact(artifact, "GPS Bookmark"); //NON-NLS
236  Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
237  Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
238  Element point = makePoint(lat, lon, getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE));
239  String bookmarkName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
240  String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
241  gpsBookmarksFolder.addContent(makePlacemark(bookmarkName, FeatureColor.BLUE, desc, timestamp, point, formattedCoordinates));
242  } catch (Exception ex) {
243  logger.log(Level.SEVERE, "Could not extract Bookmark information.", ex); //NON-NLS
244  result = ReportProgressPanel.ReportStatus.ERROR;
245  }
246  }
247  } catch (TskCoreException ex) {
248  logger.log(Level.SEVERE, "Could not get GPS Bookmarks from database.", ex); //NON-NLS
249  result = ReportProgressPanel.ReportStatus.ERROR;
250  }
251 
252  try {
254  try {
255  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
256  String desc = getDescriptionFromArtifact(artifact, "GPS Last Known Location"); //NON-NLS
257  Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
258  Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
259  Double alt = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
260  Element point = makePoint(lat, lon, alt);
261  String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
262  gpsLastKnownLocationFolder.addContent(makePlacemark("Last Known Location", FeatureColor.PURPLE, desc, timestamp, point, formattedCoordinates)); //NON-NLS
263  } catch (Exception ex) {
264  logger.log(Level.SEVERE, "Could not extract Last Known Location information.", ex); //NON-NLS
265  result = ReportProgressPanel.ReportStatus.ERROR;
266  }
267  }
268  } catch (TskCoreException ex) {
269  logger.log(Level.SEVERE, "Could not get GPS Last Known Location from database.", ex); //NON-NLS
270  result = ReportProgressPanel.ReportStatus.ERROR;
271  }
272 
273  try {
275  try {
276  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
277  String desc = getDescriptionFromArtifact(artifact, "GPS Route");
278  Double latitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
279  Double longitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
280  Double latitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
281  Double longitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
282  Double altitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
283 
284  Element route = makeLineString(latitudeStart, longitudeStart, altitude, latitudeEnd, longitudeEnd, altitude);
285  Element startingPoint = makePoint(latitudeStart, longitudeStart, altitude);
286  Element endingPoint = makePoint(latitudeEnd, longitudeEnd, altitude);
287 
288  String formattedCoordinates = String.format("%.2f, %.2f to %.2f, %.2f", latitudeStart, longitudeStart, latitudeEnd, longitudeEnd);
289  gpsRouteFolder.addContent(makePlacemark("As-the-crow-flies Route", FeatureColor.GREEN, desc, timestamp, route, formattedCoordinates)); //NON-NLS
290 
291  formattedCoordinates = String.format("%.2f, %.2f", latitudeStart, longitudeStart);
292  gpsRouteFolder.addContent(makePlacemark("Start", FeatureColor.GREEN, desc, timestamp, startingPoint, formattedCoordinates)); //NON-NLS
293 
294  formattedCoordinates = String.format("%.2f, %.2f", latitudeEnd, longitudeEnd);
295  gpsRouteFolder.addContent(makePlacemark("End", FeatureColor.GREEN, desc, timestamp, endingPoint, formattedCoordinates)); //NON-NLS
296  } catch (Exception ex) {
297  logger.log(Level.SEVERE, "Could not extract GPS Route information.", ex); //NON-NLS
298  result = ReportProgressPanel.ReportStatus.ERROR;
299  }
300  }
301  } catch (TskCoreException ex) {
302  logger.log(Level.SEVERE, "Could not get GPS Routes from database.", ex); //NON-NLS
303  result = ReportProgressPanel.ReportStatus.ERROR;
304  }
305 
306  try {
308  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
309  String desc = getDescriptionFromArtifact(artifact, "GPS Search"); //NON-NLS
310  Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
311  Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
312  Double alt = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
313  Element point = makePoint(lat, lon, alt);
314  String formattedCoordinates = String.format("%.2f, %.2f", lat, lon);
315  String searchName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
316  if (searchName == null || searchName.isEmpty()) {
317  searchName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION);
318  }
319  if (searchName == null || searchName.isEmpty()) {
320  searchName = "GPS Search";
321  }
322  gpsSearchesFolder.addContent(makePlacemark(searchName, FeatureColor.WHITE, desc, timestamp, point, formattedCoordinates)); //NON-NLS
323  }
324  } catch (TskCoreException ex) {
325  logger.log(Level.SEVERE, "Could not get GPS Searches from database.", ex); //NON-NLS
326  result = ReportProgressPanel.ReportStatus.ERROR;
327  }
328 
329  try {
331  try {
332  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
333  String desc = getDescriptionFromArtifact(artifact, "GPS Trackpoint"); //NON-NLS
334  Double lat = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
335  Double lon = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
336  Double alt = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
337  Element point = makePoint(lat, lon, alt);
338  String formattedCoordinates = String.format("%.2f, %.2f, %.2f", lat, lon, alt);
339  String trackName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
340  if (trackName == null || trackName.isEmpty()) {
341  trackName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME);
342  }
343  if (trackName == null || trackName.isEmpty()) {
344  trackName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG);
345  }
346  if (trackName == null || trackName.isEmpty()) {
347  trackName = "GPS Trackpoint";
348  }
349  gpsTrackpointsFolder.addContent(makePlacemark(trackName, FeatureColor.YELLOW, desc, timestamp, point, formattedCoordinates));
350  } catch (Exception ex) {
351  logger.log(Level.SEVERE, "Could not extract Trackpoint information.", ex); //NON-NLS
352  result = ReportProgressPanel.ReportStatus.ERROR;
353  }
354  }
355  } catch (TskCoreException ex) {
356  logger.log(Level.SEVERE, "Could not get GPS Trackpoints from database.", ex); //NON-NLS
357  result = ReportProgressPanel.ReportStatus.ERROR;
358  }
359 
360  // Copy the style sheet
361  try {
362  InputStream input = getClass().getResourceAsStream(STYLESHEETS_PATH + KML_STYLE_FILE); // Preserve slash direction
363  OutputStream output = new FileOutputStream(baseReportDir + KML_STYLE_FILE); // Preserve slash direction
364  FileUtil.copy(input, output);
365  } catch (IOException ex) {
366  logger.log(Level.SEVERE, "Error placing KML stylesheet. The .KML file will not function properly.", ex); //NON-NLS
367  result = ReportProgressPanel.ReportStatus.ERROR;
368  }
369 
370  try (FileOutputStream writer = new FileOutputStream(kmlFileFullPath)) {
371  XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
372  outputter.output(kmlDocument, writer);
373  String prependedStatus = "";
374  if (result == ReportProgressPanel.ReportStatus.ERROR) {
375  prependedStatus = "Incomplete ";
376  }
377  Case.getCurrentCase().addReport(kmlFileFullPath,
378  NbBundle.getMessage(this.getClass(), "ReportKML.genReport.srcModuleName.text"),
379  prependedStatus + NbBundle.getMessage(this.getClass(), "ReportKML.genReport.reportName"));
380  } catch (IOException ex) {
381  logger.log(Level.SEVERE, "Could not write the KML file.", ex); //NON-NLS
382  progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR);
383  } catch (TskCoreException ex) {
384  String errorMessage = String.format("Error adding %s to case as a report", kmlFileFullPath); //NON-NLS
385  logger.log(Level.SEVERE, errorMessage, ex);
386  result = ReportProgressPanel.ReportStatus.ERROR;
387  }
388 
389  progressPanel.complete(result);
390  }
391 
400  private Double getDouble(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
401  Double returnValue = null;
402  try {
403  BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
404  if (bba != null) {
405  Double value = bba.getValueDouble();
406  if (value != null) {
407  returnValue = value;
408  }
409  }
410  } catch (TskCoreException ex) {
411  logger.log(Level.SEVERE, "Error getting Double value: " + type.toString(), ex); //NON-NLS
412  }
413  return returnValue;
414  }
415 
424  private Long getLong(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
425  Long returnValue = null;
426  try {
427  BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
428  if (bba != null) {
429  Long value = bba.getValueLong();
430  if (value != null) {
431  returnValue = value;
432  }
433  }
434  } catch (TskCoreException ex) {
435  logger.log(Level.SEVERE, "Error getting Long value: " + type.toString(), ex); //NON-NLS
436  }
437  return returnValue;
438  }
439 
448  private Integer getInteger(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
449  Integer returnValue = null;
450  try {
451  BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
452  if (bba != null) {
453  Integer value = bba.getValueInt();
454  if (value != null) {
455  returnValue = value;
456  }
457  }
458  } catch (TskCoreException ex) {
459  logger.log(Level.SEVERE, "Error getting Integer value: " + type.toString(), ex); //NON-NLS
460  }
461  return returnValue;
462  }
463 
472  private String getString(BlackboardArtifact artifact, BlackboardAttribute.ATTRIBUTE_TYPE type) {
473  String returnValue = null;
474  try {
475  BlackboardAttribute bba = artifact.getAttribute(new BlackboardAttribute.Type(type));
476  if (bba != null) {
477  String value = bba.getValueString();
478  if (value != null && !value.isEmpty()) {
479  returnValue = value;
480  }
481  }
482  } catch (TskCoreException ex) {
483  logger.log(Level.SEVERE, "Error getting String value: " + type.toString(), ex); //NON-NLS
484  }
485  return returnValue;
486  }
487 
505  private String getDescriptionFromArtifact(BlackboardArtifact artifact, String featureType) {
506  StringBuilder result = new StringBuilder("<h3>" + featureType + "</h3>"); //NON-NLS
507 
508  String name = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME);
509  if (name != null && !name.isEmpty()) {
510  result.append("<b>Name:</b> ").append(name).append(SEP); //NON-NLS
511  }
512 
513  String location = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION);
514  if (location != null && !location.isEmpty()) {
515  result.append("<b>Location:</b> ").append(location).append(SEP); //NON-NLS
516  }
517 
518  Long timestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
519  if (timestamp != null) {
520  result.append("<b>Timestamp:</b> ").append(getTimeStamp(timestamp)).append(SEP); //NON-NLS
521  result.append("<b>Unix timestamp:</b> ").append(timestamp).append(SEP); //NON-NLS
522  }
523 
524  Long startingTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START);
525  if (startingTimestamp != null) {
526  result.append("<b>Starting Timestamp:</b> ").append(getTimeStamp(startingTimestamp)).append(SEP); //NON-NLS
527  result.append("<b>Starting Unix timestamp:</b> ").append(startingTimestamp).append(SEP); //NON-NLS
528  }
529 
530  Long endingTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END);
531  if (endingTimestamp != null) {
532  result.append("<b>Ending Timestamp:</b> ").append(getTimeStamp(endingTimestamp)).append(SEP); //NON-NLS
533  result.append("<b>Ending Unix timestamp:</b> ").append(endingTimestamp).append(SEP); //NON-NLS
534  }
535 
536  Long createdTimestamp = getLong(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED);
537  if (createdTimestamp != null) {
538  result.append("<b>Created Timestamp:</b> ").append(getTimeStamp(createdTimestamp)).append(SEP); //NON-NLS
539  result.append("<b>Created Unix timestamp:</b> ").append(createdTimestamp).append(SEP); //NON-NLS
540  }
541 
542  Double latitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE);
543  if (latitude != null) {
544  result.append("<b>Latitude:</b> ").append(latitude).append(SEP); //NON-NLS
545  }
546 
547  Double longitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE);
548  if (longitude != null) {
549  result.append("<b>Longitude:</b> ").append(longitude).append(SEP); //NON-NLS
550  }
551 
552  Double latitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
553  if (latitudeStart != null) {
554  result.append("<b>Latitude Start:</b> ").append(latitudeStart).append(SEP); //NON-NLS
555  }
556 
557  Double longitudeStart = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
558  if (longitudeStart != null) {
559  result.append("<b>Longitude Start:</b> ").append(longitudeStart).append(SEP); //NON-NLS
560  }
561 
562  Double latitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
563  if (latitudeEnd != null) {
564  result.append("<b>Latitude End:</b> ").append(latitudeEnd).append(SEP); //NON-NLS
565  }
566 
567  Double longitudeEnd = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
568  if (longitudeEnd != null) {
569  result.append("<b>Longitude End:</b> ").append(longitudeEnd).append(SEP); //NON-NLS
570  }
571 
572  Double velocity = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_VELOCITY);
573  if (velocity != null) {
574  result.append("<b>Velocity:</b> ").append(velocity).append(SEP); //NON-NLS
575  }
576 
577  Double altitude = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
578  if (altitude != null) {
579  result.append("<b>Altitude:</b> ").append(altitude).append(SEP); //NON-NLS
580  }
581 
582  Double bearing = getDouble(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_BEARING);
583  if (bearing != null) {
584  result.append("<b>Bearing:</b> ").append(bearing).append(SEP); //NON-NLS
585  }
586 
587  Integer hPrecision = getInteger(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_HPRECISION);
588  if (hPrecision != null) {
589  result.append("<b>Horizontal Precision Figure of Merit:</b> ").append(hPrecision).append(SEP); //NON-NLS
590  }
591 
592  Integer vPrecision = getInteger(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_VPRECISION);
593  if (vPrecision != null) {
594  result.append("<b>Vertical Precision Figure of Merit:</b> ").append(vPrecision).append(SEP); //NON-NLS
595  }
596 
597  String mapDatum = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_MAPDATUM);
598  if (mapDatum != null && !mapDatum.isEmpty()) {
599  result.append("<b>Map Datum:</b> ").append(mapDatum).append(SEP); //NON-NLS
600  }
601 
602  String programName = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME);
603  if (programName != null && !programName.isEmpty()) {
604  result.append("<b>Reported by:</b> ").append(programName).append(SEP); //NON-NLS
605  }
606 
607  String flag = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG);
608  if (flag != null && !flag.isEmpty()) {
609  result.append("<b>Flag:</b> ").append(flag).append(SEP); //NON-NLS
610  }
611 
612  String pathSource = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH_SOURCE);
613  if (pathSource != null && !pathSource.isEmpty()) {
614  result.append("<b>Source:</b> ").append(pathSource).append(SEP); //NON-NLS
615  }
616 
617  String deviceMake = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MAKE);
618  if (deviceMake != null && !deviceMake.isEmpty()) {
619  result.append("<b>Device Make:</b> ").append(deviceMake).append(SEP); //NON-NLS
620  }
621 
622  String deviceModel = getString(artifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_MODEL);
623  if (deviceModel != null && !deviceModel.isEmpty()) {
624  result.append("<b>Device Model:</b> ").append(deviceModel).append(SEP); //NON-NLS
625  }
626 
627  return result.toString();
628  }
629 
630  private String getTimeStamp(long timeStamp) {
631  return kmlDateFormat.format(new java.util.Date(timeStamp * 1000));
632  }
633 
647  private Element makePoint(Double latitude, Double longitude, Double altitude) {
648  if (latitude == null) {
649  latitude = 0.0;
650  }
651  if (longitude == null) {
652  longitude = 0.0;
653  }
654  if (altitude == null) {
655  altitude = 0.0;
656  }
657  Element point = new Element("Point", ns); //NON-NLS
658 
659  // KML uses lon, lat. Deliberately reversed.
660  Element coordinates = new Element("coordinates", ns).addContent(longitude + "," + latitude + "," + altitude); //NON-NLS
661 
662  if (altitude != 0) {
663  /*
664  Though we are including a non-zero altitude, clamp it to the
665  ground because inaccuracies from the GPS data can cause the terrain
666  to occlude points when zoomed in otherwise. Show the altitude, but
667  keep the point clamped to the ground. We may change this later for
668  flying GPS sensors.
669  */
670  Element altitudeMode = new Element("altitudeMode", ns).addContent("clampToGround"); //NON-NLS
671  point.addContent(altitudeMode);
672  }
673  point.addContent(coordinates);
674 
675  return point;
676  }
677 
695  private Element makeLineString(Double startLatitude, Double startLongitude, Double startAltitude, Double stopLatitude, Double stopLongitude, Double stopAltitude) {
696  if (startLatitude == null) {
697  startLatitude = 0.0;
698  }
699  if (startLongitude == null) {
700  startLongitude = 0.0;
701  }
702  if (startAltitude == null) {
703  startAltitude = 0.0;
704  }
705  if (stopLatitude == null) {
706  stopLatitude = 0.0;
707  }
708  if (stopLongitude == null) {
709  stopLongitude = 0.0;
710  }
711  if (stopAltitude == null) {
712  stopAltitude = 0.0;
713  }
714 
715  Element lineString = new Element("LineString", ns); //NON-NLS
716  lineString.addContent(new Element("extrude", ns).addContent("1")); //NON-NLS
717  lineString.addContent(new Element("tessellate", ns).addContent("1")); //NON-NLS
718  lineString.addContent(new Element("altitudeMode", ns).addContent("clampToGround")); //NON-NLS
719  // KML uses lon, lat. Deliberately reversed.
720  lineString.addContent(new Element("coordinates", ns).addContent(
721  startLongitude + "," + startLatitude + ",0.0,"
722  + stopLongitude + "," + stopLatitude + ",0.0")); //NON-NLS
723  return lineString;
724  }
725 
740  private Element makePlacemark(String name, FeatureColor color, String description, Long timestamp, Element feature, String coordinates) {
741  Element placemark = new Element("Placemark", ns); //NON-NLS
742  if (name != null && !name.isEmpty()) {
743  placemark.addContent(new Element("name", ns).addContent(name)); //NON-NLS
744  } else if (timestamp != null) {
745  placemark.addContent(new Element("name", ns).addContent(getTimeStamp(timestamp))); //NON-NLS
746  } else {
747  placemark.addContent(new Element("name", ns).addContent("")); //NON-NLS
748  }
749  placemark.addContent(new Element("styleUrl", ns).addContent(color.getColor())); //NON-NLS
750  placemark.addContent(new Element("description", ns).addContent(description)); //NON-NLS
751  if (timestamp != null) {
752  Element time = new Element("TimeStamp", ns); //NON-NLS
753  time.addContent(new Element("when", ns).addContent(getTimeStamp(timestamp))); //NON-NLS
754  placemark.addContent(time);
755  }
756  placemark.addContent(feature);
757  if (coordinates != null && !coordinates.isEmpty()) {
758  placemark.addContent(new Element("snippet", ns).addContent(coordinates)); //NON-NLS
759  }
760  return placemark;
761  }
762 
778  private Element makePlacemarkWithPicture(String name, FeatureColor color, String description, Long timestamp, Element feature, Path path, String coordinates) {
779  Element placemark = new Element("Placemark", ns); //NON-NLS
780  Element desc = new Element("description", ns); //NON-NLS
781  if (name != null && !name.isEmpty()) {
782  placemark.addContent(new Element("name", ns).addContent(name)); //NON-NLS
783  String image = "<img src='" + name + "' width='400'/>"; //NON-NLS
784  desc.addContent(image);
785  }
786  placemark.addContent(new Element("styleUrl", ns).addContent(color.getColor())); //NON-NLS
787  if (path != null) {
788  String pathAsString = path.toString();
789  if (pathAsString != null && !pathAsString.isEmpty()) {
790  desc.addContent(description + "<b>Source Path:</b> " + pathAsString);
791  }
792  }
793  placemark.addContent(desc);
794 
795  if (timestamp != null) {
796  Element time = new Element("TimeStamp", ns); //NON-NLS
797  time.addContent(new Element("when", ns).addContent(getTimeStamp(timestamp))); //NON-NLS
798  placemark.addContent(time);
799  }
800  placemark.addContent(feature);
801  if (coordinates != null && !coordinates.isEmpty()) {
802  placemark.addContent(new Element("snippet", ns).addContent(coordinates)); //NON-NLS
803  }
804  return placemark;
805  }
806 
815  private void copyFileUsingStream(AbstractFile inputFile, File outputFile) throws IOException {
816  byte[] buffer = new byte[65536];
817  int length;
818  outputFile.createNewFile();
819  try (InputStream is = new ReadContentInputStream(inputFile);
820  OutputStream os = new FileOutputStream(outputFile)) {
821  while ((length = is.read(buffer)) != -1) {
822  os.write(buffer, 0, length);
823  }
824  }
825  }
826 
827  @Override
828  public String getName() {
829  String name = NbBundle.getMessage(this.getClass(), "ReportKML.getName.text");
830  return name;
831  }
832 
833  @Override
834  public String getRelativeFilePath() {
835  return "ReportKML.kml"; //NON-NLS
836  }
837 
838  @Override
839  public String getDescription() {
840  String desc = NbBundle.getMessage(this.getClass(), "ReportKML.getDesc.text");
841  return desc;
842  }
843 
844  @Override
845  public JPanel getConfigurationPanel() {
846  return null; // No configuration panel
847  }
848 
859  private static String removeLeadingImgAndVol(String uniquePath) {
860  // split the path into parts
861  String[] pathSegments = uniquePath.replaceFirst("^/*", "").split("/"); //NON-NLS
862 
863  // Replace image/volume name if they exist in specific entries
864  if (pathSegments.length > 0) {
865  pathSegments[0] = pathSegments[0].replaceFirst("^img_", ""); //NON-NLS
866  }
867  if (pathSegments.length > 1) {
868  pathSegments[1] = pathSegments[1].replaceFirst("^vol_", ""); //NON-NLS
869  }
870 
871  // Assemble the path
872  StringBuilder strbuf = new StringBuilder();
873  for (String segment : pathSegments) {
874  if (!segment.isEmpty()) {
875  strbuf.append("/").append(segment);
876  }
877  }
878  return strbuf.toString();
879  }
880 }
ArrayList< BlackboardArtifact > getBlackboardArtifacts(int artifactTypeID)
AbstractFile getAbstractFileById(long id)
BlackboardAttribute getAttribute(BlackboardAttribute.Type attributeType)

Copyright © 2012-2016 Basis Technology. Generated on: Mon Apr 24 2017
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.