org.sleuthkit.autopsy.report.ReportKML.java Source code

Java tutorial

Introduction

Here is the source code for org.sleuthkit.autopsy.report.ReportKML.java

Source

/*
 *
 * 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/&gt;  \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
    }
}