Autopsy  4.0
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 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.*;
29 import org.sleuthkit.datamodel.BlackboardArtifact;
30 import java.io.BufferedReader;
31 import java.io.BufferedWriter;
32 import java.io.File;
33 import java.io.FileOutputStream;
34 import java.io.FileReader;
35 import java.io.FileWriter;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.OutputStream;
39 import java.util.logging.Level;
40 import org.jdom2.Document;
41 import org.jdom2.Element;
42 import org.jdom2.Namespace;
43 import org.jdom2.output.Format;
44 import org.jdom2.output.XMLOutputter;
45 import org.apache.commons.lang.StringEscapeUtils;
46 
50 class ReportKML implements GeneralReportModule {
51 
52  private static final Logger logger = Logger.getLogger(ReportKML.class.getName());
53  private static ReportKML instance = null;
54  private Case currentCase;
55  private SleuthkitCase skCase;
56  private String reportPath;
57 
58  // Hidden constructor for the report
59  private ReportKML() {
60  }
61 
62  // Get the default implementation of this report
63  public static synchronized ReportKML getDefault() {
64  if (instance == null) {
65  instance = new ReportKML();
66  }
67  return instance;
68  }
69 
76  @Override
77  public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
78 
79  // Start the progress bar and setup the report
80  progressPanel.setIndeterminate(false);
81  progressPanel.start();
82  progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying"));
83  reportPath = baseReportDir + "ReportKML.kml"; //NON-NLS
84  String reportPath2 = baseReportDir + "ReportKML.txt"; //NON-NLS
85  currentCase = Case.getCurrentCase();
86  skCase = currentCase.getSleuthkitCase();
87 
88  progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.loading"));
89  // Check if ingest has finished
90  String ingestwarning = "";
91  if (IngestManager.getInstance().isIngestRunning()) {
92  ingestwarning = NbBundle.getMessage(this.getClass(), "ReportBodyFile.ingestWarning.text");
93  }
94  progressPanel.setMaximumProgress(5);
95  progressPanel.increment();
96 
97  // @@@ BC: I don't get why we do this in two passes.
98  // Why not just print the coordinates as we find them and make some utility methods to do the printing?
99  // Should pull out time values for all of these points and store in TimeSpan element
100  try {
101  try (BufferedWriter out = new BufferedWriter(new FileWriter(reportPath2))) {
102 
103  double lat = 0; // temp latitude
104  double lon = 0; //temp longitude
105  AbstractFile aFile;
106  String geoPath = ""; // will hold values of images to put in kml
107  String imageName = "";
108 
109  File f;
110  for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)) {
111  lat = 0;
112  lon = 0;
113  geoPath = "";
114  String extractedToPath;
115  for (BlackboardAttribute attribute : artifact.getAttributes()) {
116  if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
117  {
118 
119  lat = attribute.getValueDouble();
120  }
121  if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
122  {
123  lon = attribute.getValueDouble();
124  }
125  }
126  if (lon != 0 && lat != 0) {
127  aFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
128 
129  if (aFile != null) {
130  extractedToPath = reportPath + aFile.getName();
131  geoPath = extractedToPath;
132  f = new File(extractedToPath);
133  f.createNewFile();
134  copyFileUsingStream(aFile, f);
135  imageName = aFile.getName();
136  }
137  out.write(String.valueOf(lat));
138  out.write(";");
139  out.write(String.valueOf(lon));
140  out.write(";");
141  out.write(String.valueOf(geoPath));
142  out.write(";");
143  out.write(String.valueOf(imageName));
144  out.write("\n");
145  // lat lon path name
146  }
147  }
148 
149  for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) {
150  lat = 0;
151  lon = 0;
152  for (BlackboardAttribute attribute : artifact.getAttributes()) {
153  if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID()) //latitude
154  {
155  lat = attribute.getValueDouble();
156  }
157  if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID()) //longitude
158  {
159  lon = attribute.getValueDouble();
160  }
161  }
162  if (lon != 0 && lat != 0) {
163  out.write(lat + ";" + lon + "\n");
164  }
165  }
166 
167  for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) {
168  lat = 0;
169  lon = 0;
170  double destlat = 0;
171  double destlon = 0;
172  String name = "";
173  String location = "";
174  for (BlackboardAttribute attribute : artifact.getAttributes()) {
175  if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()) //latitude
176  {
177  lat = attribute.getValueDouble();
178  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID()) //longitude
179  {
180  destlat = attribute.getValueDouble();
181  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID()) //longitude
182  {
183  lon = attribute.getValueDouble();
184  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID()) //longitude
185  {
186  destlon = attribute.getValueDouble();
187  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID()) //longitude
188  {
189  name = attribute.getValueString();
190  } else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID()) //longitude
191  {
192  location = attribute.getValueString();
193  }
194  }
195 
196  // @@@ Should do something more fancy with these in KML and store them as a single point.
197  String display = name;
198  if (display.isEmpty()) {
199  display = location;
200  }
201 
202  if (lon != 0 && lat != 0) {
203  out.write(NbBundle.getMessage(this.getClass(), "ReportKML.latLongStartPoint", lat, lon, display));
204  }
205  if (destlat != 0 && destlon != 0) {
206  out.write(NbBundle.getMessage(this.getClass(), "ReportKML.latLongEndPoint", destlat, destlon,
207  display));
208  }
209  }
210 
211  out.flush();
212 
213  progressPanel.increment();
214  /*
215  * Step 1: generate XML stub
216  */
217  Namespace ns = Namespace.getNamespace("", "http://earth.google.com/kml/2.2"); //NON-NLS
218  // kml
219  Element kml = new Element("kml", ns); //NON-NLS
220  Document kmlDocument = new Document(kml);
221 
222  // Document
223  Element document = new Element("Document", ns); //NON-NLS
224  kml.addContent(document);
225 
226  // name
227  Element name = new Element("name", ns); //NON-NLS
228  name.setText("Java Generated KML Document"); //NON-NLS
229  document.addContent(name);
230 
231  /*
232  * Step 2: add in Style elements
233  */
234  // Style
235  Element style = new Element("Style", ns); //NON-NLS
236  style.setAttribute("id", "redIcon"); //NON-NLS
237  document.addContent(style);
238 
239  // IconStyle
240  Element iconStyle = new Element("IconStyle", ns); //NON-NLS
241  style.addContent(iconStyle);
242 
243  // color
244  Element color = new Element("color", ns); //NON-NLS
245  color.setText("990000ff"); //NON-NLS
246  iconStyle.addContent(color);
247 
248  // Icon
249  Element icon = new Element("Icon", ns); //NON-NLS
250  iconStyle.addContent(icon);
251 
252  // href
253  Element href = new Element("href", ns); //NON-NLS
254  href.setText("http://www.cs.mun.ca/~hoeber/teaching/cs4767/notes/02.1-kml/circle.png"); //NON-NLS
255  icon.addContent(href);
256  progressPanel.increment();
257  /*
258  * Step 3: read data from source location and add in a Placemark
259  * for each data element
260  */
261 
262  File file = new File(reportPath2);
263  try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
264  String line = reader.readLine();
265  while (line != null) {
266  String[] lineParts = line.split(";");
267  if (lineParts.length > 1) {
268  String coordinates = lineParts[1].trim() + "," + lineParts[0].trim(); //lat,lon
269  // Placemark
270  Element placemark = new Element("Placemark", ns); //NON-NLS
271  document.addContent(placemark);
272 
273  if (lineParts.length == 4) {
274  // name
275  Element pmName = new Element("name", ns); //NON-NLS
276  pmName.setText(lineParts[3].trim());
277  placemark.addContent(pmName);
278 
279  String savedPath = lineParts[2].trim();
280  if (savedPath.isEmpty() == false) {
281  // Path
282  Element pmPath = new Element("Path", ns); //NON-NLS
283  pmPath.setText(savedPath);
284  placemark.addContent(pmPath);
285 
286  // description
287  Element pmDescription = new Element("description", ns); //NON-NLS
288  String xml = "<![CDATA[ \n" + " <img src='file:///" + savedPath + "' width='400' /><br/&gt; \n"; //NON-NLS
289  StringEscapeUtils.unescapeXml(xml);
290  pmDescription.setText(xml);
291  placemark.addContent(pmDescription);
292  }
293  }
294 
295  // styleUrl
296  Element pmStyleUrl = new Element("styleUrl", ns); //NON-NLS
297  pmStyleUrl.setText("#redIcon"); //NON-NLS
298  placemark.addContent(pmStyleUrl);
299 
300  // Point
301  Element pmPoint = new Element("Point", ns); //NON-NLS
302  placemark.addContent(pmPoint);
303 
304  // coordinates
305  Element pmCoordinates = new Element("coordinates", ns); //NON-NLS
306 
307  pmCoordinates.setText(coordinates);
308  pmPoint.addContent(pmCoordinates);
309 
310  }
311 
312  // read the next line
313  line = reader.readLine();
314  }
315 
316  }
317  progressPanel.increment();
318  /*
319  * Step 4: write the XML file
320  */
321  try (FileOutputStream writer = new FileOutputStream(reportPath)) {
322  XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat());
323  outputter.output(kmlDocument, writer);
324  Case.getCurrentCase().addReport(reportPath, NbBundle.getMessage(this.getClass(),
325  "ReportKML.genReport.srcModuleName.text"), "");
326  } catch (IOException ex) {
327  logger.log(Level.WARNING, "Could not write the KML file.", ex); //NON-NLS
328  } catch (TskCoreException ex) {
329  String errorMessage = String.format("Error adding %s to case as a report", reportPath); //NON-NLS
330  logger.log(Level.SEVERE, errorMessage, ex);
331  }
332  } catch (IOException ex) {
333  logger.log(Level.WARNING, "Could not write the KML report.", ex); //NON-NLS
334  }
335  progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR);
336  } catch (TskCoreException ex) {
337  logger.log(Level.WARNING, "Failed to get the unique path.", ex); //NON-NLS
338  }
339  progressPanel.increment();
340  progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE);
341  }
342 
343  public static void copyFileUsingStream(AbstractFile file, File jFile) throws IOException {
344  InputStream is = new ReadContentInputStream(file);
345  OutputStream os = new FileOutputStream(jFile);
346  byte[] buffer = new byte[8192];
347  int length;
348  try {
349  while ((length = is.read(buffer)) != -1) {
350  os.write(buffer, 0, length);
351  }
352 
353  } finally {
354  is.close();
355  os.close();
356  }
357  }
358 
359  @Override
360  public String getName() {
361  String name = NbBundle.getMessage(this.getClass(), "ReportKML.getName.text");
362  return name;
363  }
364 
365  @Override
366  public String getRelativeFilePath() {
367  return "ReportKML.kml"; //NON-NLS
368  }
369 
370  @Override
371  public String getDescription() {
372  String desc = NbBundle.getMessage(this.getClass(), "ReportKML.getDesc.text");
373  return desc;
374  }
375 
376  @Override
377  public JPanel getConfigurationPanel() {
378  return null; // No configuration panel
379  }
380 }

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