Java tutorial
/* * * Autopsy Forensic Browser * * Copyright 2014 Basis Technology Corp. * contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.report; import javax.swing.JPanel; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; 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.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; /** * Generates a KML file based on geo coordinates store in blackboard. */ class ReportKML implements GeneralReportModule { private static final Logger logger = Logger.getLogger(ReportKML.class.getName()); private static ReportKML instance = null; private Case currentCase; private SleuthkitCase skCase; private String reportPath; // Hidden constructor for the report private ReportKML() { } // Get the default implementation of this report public static synchronized ReportKML getDefault() { if (instance == null) { instance = new ReportKML(); } return instance; } /** * Generates a body file format report for use with the MAC time tool. * * @param path path to save the report * @param progressPanel panel to update the report's progress */ @Override public void generateReport(String path, ReportProgressPanel progressPanel) { // Start the progress bar and setup the report progressPanel.setIndeterminate(false); progressPanel.start(); progressPanel.updateStatusLabel(NbBundle.getMessage(this.getClass(), "ReportKML.progress.querying")); reportPath = path + "ReportKML.kml"; //NON-NLS String reportPath2 = path + "ReportKML.txt"; //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 { BufferedWriter out = null; try { out = new BufferedWriter(new FileWriter(reportPath2)); 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.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE .getTypeID()) //latitude { lat = attribute.getValueDouble(); } if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE .getTypeID()) //longitude { lon = attribute.getValueDouble(); } } if (lon != 0 && lat != 0) { aFile = artifact.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()); 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.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE .getTypeID()) //latitude { lat = attribute.getValueDouble(); } if (attribute.getAttributeTypeID() == 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 .getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START .getTypeID()) //latitude { lat = attribute.getValueDouble(); } else if (attribute .getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END .getTypeID()) //longitude { destlat = attribute.getValueDouble(); } else if (attribute .getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START .getTypeID()) //longitude { lon = attribute.getValueDouble(); } else if (attribute .getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END .getTypeID()) //longitude { destlon = attribute.getValueDouble(); } else if (attribute.getAttributeTypeID() == BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME .getTypeID()) //longitude { name = attribute.getValueString(); } else if (attribute.getAttributeTypeID() == 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(); out.close(); 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 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 document.addContent(name); /* * Step 2: add in Style elements */ // Style Element style = new Element("Style", ns); //NON-NLS style.setAttribute("id", "redIcon"); //NON-NLS document.addContent(style); // IconStyle Element iconStyle = new Element("IconStyle", ns); //NON-NLS style.addContent(iconStyle); // color Element color = new Element("color", ns); //NON-NLS color.setText("990000ff"); //NON-NLS iconStyle.addContent(color); // Icon Element icon = new Element("Icon", ns); //NON-NLS iconStyle.addContent(icon); // 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); BufferedReader reader; 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 { XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); FileOutputStream writer = new FileOutputStream(reportPath); outputter.output(kmlDocument, writer); writer.close(); Case.getCurrentCase().addReport(reportPath, NbBundle.getMessage(this.getClass(), "ReportKML.genReport.srcModuleName.text"), ""); } 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 } progressPanel.complete(); } catch (TskCoreException ex) { logger.log(Level.WARNING, "Failed to get the unique path.", ex); //NON-NLS } progressPanel.increment(); progressPanel.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; try { while ((length = is.read(buffer)) != -1) { os.write(buffer, 0, length); } } finally { is.close(); os.close(); } } @Override public String getName() { String name = NbBundle.getMessage(this.getClass(), "ReportKML.getName.text"); return name; } @Override public String getRelativeFilePath() { return "ReportKML.kml"; //NON-NLS } @Override public String getDescription() { String desc = NbBundle.getMessage(this.getClass(), "ReportKML.getDesc.text"); return desc; } @Override public JPanel getConfigurationPanel() { return null; // No configuration panel } }