20 package org.sleuthkit.autopsy.report;
22 import javax.swing.JPanel;
24 import org.openide.util.NbBundle;
30 import java.io.BufferedReader;
31 import java.io.BufferedWriter;
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;
50 class ReportKML
implements GeneralReportModule {
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;
63 public static synchronized ReportKML getDefault() {
64 if (instance == null) {
65 instance =
new ReportKML();
77 public void generateReport(String baseReportDir, ReportProgressPanel progressPanel) {
80 progressPanel.setIndeterminate(
false);
81 progressPanel.start();
82 progressPanel.updateStatusLabel(NbBundle.getMessage(
this.getClass(),
"ReportKML.progress.querying"));
83 reportPath = baseReportDir +
"ReportKML.kml";
84 String reportPath2 = baseReportDir +
"ReportKML.txt";
85 currentCase = Case.getCurrentCase();
86 skCase = currentCase.getSleuthkitCase();
88 progressPanel.updateStatusLabel(NbBundle.getMessage(
this.getClass(),
"ReportKML.progress.loading"));
90 String ingestwarning =
"";
91 if (IngestManager.getInstance().isIngestRunning()) {
92 ingestwarning = NbBundle.getMessage(this.getClass(),
"ReportBodyFile.ingestWarning.text");
94 progressPanel.setMaximumProgress(5);
95 progressPanel.increment();
101 try (BufferedWriter out =
new BufferedWriter(
new FileWriter(reportPath2))) {
107 String imageName =
"";
110 for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF)) {
114 String extractedToPath;
115 for (BlackboardAttribute attribute : artifact.getAttributes()) {
116 if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())
119 lat = attribute.getValueDouble();
121 if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())
123 lon = attribute.getValueDouble();
126 if (lon != 0 && lat != 0) {
127 aFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID());
130 extractedToPath = reportPath + aFile.getName();
131 geoPath = extractedToPath;
132 f =
new File(extractedToPath);
134 copyFileUsingStream(aFile, f);
135 imageName = aFile.getName();
137 out.write(String.valueOf(lat));
139 out.write(String.valueOf(lon));
141 out.write(String.valueOf(geoPath));
143 out.write(String.valueOf(imageName));
149 for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT)) {
152 for (BlackboardAttribute attribute : artifact.getAttributes()) {
153 if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID())
155 lat = attribute.getValueDouble();
157 if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID())
159 lon = attribute.getValueDouble();
162 if (lon != 0 && lat != 0) {
163 out.write(lat +
";" + lon +
"\n");
167 for (BlackboardArtifact artifact : skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE)) {
173 String location =
"";
174 for (BlackboardAttribute attribute : artifact.getAttributes()) {
175 if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID())
177 lat = attribute.getValueDouble();
178 }
else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID())
180 destlat = attribute.getValueDouble();
181 }
else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID())
183 lon = attribute.getValueDouble();
184 }
else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID())
186 destlon = attribute.getValueDouble();
187 }
else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID())
189 name = attribute.getValueString();
190 }
else if (attribute.getAttributeType().getTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION.getTypeID())
192 location = attribute.getValueString();
197 String display = name;
198 if (display.isEmpty()) {
202 if (lon != 0 && lat != 0) {
203 out.write(NbBundle.getMessage(
this.getClass(),
"ReportKML.latLongStartPoint", lat, lon, display));
205 if (destlat != 0 && destlon != 0) {
206 out.write(NbBundle.getMessage(
this.getClass(),
"ReportKML.latLongEndPoint", destlat, destlon,
213 progressPanel.increment();
217 Namespace ns = Namespace.getNamespace(
"",
"http://earth.google.com/kml/2.2");
219 Element kml =
new Element(
"kml", ns);
220 Document kmlDocument =
new Document(kml);
223 Element document =
new Element(
"Document", ns);
224 kml.addContent(document);
227 Element name =
new Element(
"name", ns);
228 name.setText(
"Java Generated KML Document");
229 document.addContent(name);
235 Element style =
new Element(
"Style", ns);
236 style.setAttribute(
"id",
"redIcon");
237 document.addContent(style);
240 Element iconStyle =
new Element(
"IconStyle", ns);
241 style.addContent(iconStyle);
244 Element color =
new Element(
"color", ns);
245 color.setText(
"990000ff");
246 iconStyle.addContent(color);
249 Element icon =
new Element(
"Icon", ns);
250 iconStyle.addContent(icon);
253 Element href =
new Element(
"href", ns);
254 href.setText(
"http://www.cs.mun.ca/~hoeber/teaching/cs4767/notes/02.1-kml/circle.png");
255 icon.addContent(href);
256 progressPanel.increment();
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();
270 Element placemark =
new Element(
"Placemark", ns);
271 document.addContent(placemark);
273 if (lineParts.length == 4) {
275 Element pmName =
new Element(
"name", ns);
276 pmName.setText(lineParts[3].trim());
277 placemark.addContent(pmName);
279 String savedPath = lineParts[2].trim();
280 if (savedPath.isEmpty() ==
false) {
282 Element pmPath =
new Element(
"Path", ns);
283 pmPath.setText(savedPath);
284 placemark.addContent(pmPath);
287 Element pmDescription =
new Element(
"description", ns);
288 String xml =
"<![CDATA[ \n" +
" <img src='file:///" + savedPath +
"' width='400' /><br/> \n";
289 StringEscapeUtils.unescapeXml(xml);
290 pmDescription.setText(xml);
291 placemark.addContent(pmDescription);
296 Element pmStyleUrl =
new Element(
"styleUrl", ns);
297 pmStyleUrl.setText(
"#redIcon");
298 placemark.addContent(pmStyleUrl);
301 Element pmPoint =
new Element(
"Point", ns);
302 placemark.addContent(pmPoint);
305 Element pmCoordinates =
new Element(
"coordinates", ns);
307 pmCoordinates.setText(coordinates);
308 pmPoint.addContent(pmCoordinates);
313 line = reader.readLine();
317 progressPanel.increment();
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);
328 }
catch (TskCoreException ex) {
329 String errorMessage = String.format(
"Error adding %s to case as a report", reportPath);
330 logger.log(Level.SEVERE, errorMessage, ex);
332 }
catch (IOException ex) {
333 logger.log(Level.WARNING,
"Could not write the KML report.", ex);
335 progressPanel.complete(ReportProgressPanel.ReportStatus.ERROR);
336 }
catch (TskCoreException ex) {
337 logger.log(Level.WARNING,
"Failed to get the unique path.", ex);
339 progressPanel.increment();
340 progressPanel.complete(ReportProgressPanel.ReportStatus.COMPLETE);
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];
349 while ((length = is.read(buffer)) != -1) {
350 os.write(buffer, 0, length);
360 public String getName() {
361 String name = NbBundle.getMessage(this.getClass(),
"ReportKML.getName.text");
366 public String getRelativeFilePath() {
367 return "ReportKML.kml";
371 public String getDescription() {
372 String desc = NbBundle.getMessage(this.getClass(),
"ReportKML.getDesc.text");
377 public JPanel getConfigurationPanel() {