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

Copyright © 2012-2015 Basis Technology. Generated on: Mon Oct 19 2015
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.