org.sleuthkit.autopsy.timeline.snapshot.SnapShotReportWriter.java Source code

Java tutorial

Introduction

Here is the source code for org.sleuthkit.autopsy.timeline.snapshot.SnapShotReportWriter.java

Source

/*
 * Autopsy Forensic Browser
 *
 * Copyright 2016 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.timeline.snapshot;

import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheFactory;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import javax.imageio.ImageIO;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.format.DateTimeFormat;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.report.ReportBranding;
import org.sleuthkit.autopsy.timeline.zooming.ZoomParams;

/**
 * Generate and write the Timeline snapshot report to disk.
 */
public class SnapShotReportWriter {

    /**
     * mustache.java template factory.
     */
    private final static MustacheFactory mf = new DefaultMustacheFactory();

    private final Case currentCase;
    private final Path reportFolderPath;
    private final String reportName;
    private final ReportBranding reportBranding;

    private final ZoomParams zoomParams;
    private final Date generationDate;
    private final BufferedImage image;

    /**
     * Constructor
     *
     * @param currentCase      The Case to write a report for.
     * @param reportFolderPath The Path to the folder that will contain the
     *                         report.
     * @param reportName       The name of the report.
     * @param zoomParams       The ZoomParams in effect when the snapshot was
     *                         taken.
     * @param generationDate   The generation Date of the report.
     * @param snapshot         A snapshot of the view to include in the
     *                         report.
     */
    public SnapShotReportWriter(Case currentCase, Path reportFolderPath, String reportName, ZoomParams zoomParams,
            Date generationDate, BufferedImage snapshot) {
        this.currentCase = currentCase;
        this.reportFolderPath = reportFolderPath;
        this.reportName = reportName;
        this.zoomParams = zoomParams;
        this.generationDate = generationDate;
        this.image = snapshot;

        this.reportBranding = new ReportBranding();
    }

    /**
     * Generate and write the report to disk.
     *
     * @return The Path to the "main file" of the report. This is the file that
     *         Autopsy shows in the results view when the Reports Node is
     *         selected in the DirectoryTree.
     *
     * @throws IOException If there is a problem writing the report.
     */
    public Path writeReport() throws IOException {
        //ensure directory exists 
        Files.createDirectories(reportFolderPath);

        //save the snapshot in the report directory
        ImageIO.write(image, "png", reportFolderPath.resolve("snapshot.png").toFile()); //NON-NLS

        copyResources();

        writeSummaryHTML();
        writeSnapShotHTMLFile();
        return writeIndexHTML();
    }

    /**
     * Generate and write the html page that shows the snapshot and the state of
     * the ZoomParams
     *
     * @throws IOException If there is a problem writing the html file to disk.
     */
    private void writeSnapShotHTMLFile() throws IOException {
        //make a map of context objects to resolve template paramaters against
        HashMap<String, Object> snapShotContext = new HashMap<>();
        snapShotContext.put("reportTitle", reportName); //NON-NLS
        snapShotContext.put("startTime",
                zoomParams.getTimeRange().getStart().toString(DateTimeFormat.fullDateTime())); //NON-NLS
        snapShotContext.put("endTime", zoomParams.getTimeRange().getEnd().toString(DateTimeFormat.fullDateTime())); //NON-NLS
        snapShotContext.put("zoomParams", zoomParams); //NON-NLS

        fillTemplateAndWrite("/org/sleuthkit/autopsy/timeline/snapshot/snapshot_template.html", "Snapshot",
                snapShotContext, reportFolderPath.resolve("snapshot.html")); //NON-NLS
    }

    /**
     * Generate and write the main html page with frames for navigation on the
     * left and content on the right.
     *
     * @return The Path of the written html file.
     *
     * @throws IOException If there is a problem writing the html file to disk.
     */
    private Path writeIndexHTML() throws IOException {
        //make a map of context objects to resolve template paramaters against
        HashMap<String, Object> indexContext = new HashMap<>();
        indexContext.put("reportBranding", reportBranding); //NON-NLS
        indexContext.put("reportName", reportName); //NON-NLS
        Path reportIndexFile = reportFolderPath.resolve("index.html"); //NON-NLS

        fillTemplateAndWrite("/org/sleuthkit/autopsy/timeline/snapshot/index_template.html", "Index", indexContext,
                reportIndexFile); //NON-NLS
        return reportIndexFile;
    }

    /**
     * * Generate and write the summary of the current case for this report.
     *
     * @throws IOException If there is a problem writing the html file to disk.
     */
    private void writeSummaryHTML() throws IOException {
        //make a map of context objects to resolve template paramaters against
        HashMap<String, Object> summaryContext = new HashMap<>();
        summaryContext.put("reportName", reportName); //NON-NLS
        summaryContext.put("reportBranding", reportBranding); //NON-NLS
        summaryContext.put("generationDateTime",
                new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(generationDate)); //NON-NLS
        summaryContext.put("ingestRunning", IngestManager.getInstance().isIngestRunning()); //NON-NLS
        summaryContext.put("currentCase", currentCase); //NON-NLS

        fillTemplateAndWrite("/org/sleuthkit/autopsy/timeline/snapshot/summary_template.html", "Summary",
                summaryContext, reportFolderPath.resolve("summary.html")); //NON-NLS
    }

    /**
     * Fill in the mustache template at the given location using the values from
     * the given context object and save it to the given outPutFile.
     *
     * @param templateLocation The location of the template. suitible for use
     *                         with Class.getResourceAsStream
     * @param templateName     The name of the tempalte. (Used by mustache to
     *                         cache templates?)
     * @param context          The contect to use to fill in the template
     *                         values.
     * @param outPutFile       The filled in tempalte will be saced at this
     *                         Path.
     *
     * @throws IOException If there is a problem saving the filled in template
     *                     to disk.
     */
    private void fillTemplateAndWrite(final String templateLocation, final String templateName, Object context,
            final Path outPutFile) throws IOException {

        Mustache summaryMustache = mf.compile(
                new InputStreamReader(SnapShotReportWriter.class.getResourceAsStream(templateLocation)),
                templateName);
        try (Writer writer = Files.newBufferedWriter(outPutFile, Charset.forName("UTF-8"))) { //NON-NLS
            summaryMustache.execute(writer, context);
        }
    }

    /**
     * Copy static resources (static html, css, images, etc) to the reports
     * folder.
     *
     * @throws IOException If there is a problem copying the resources.
     */
    private void copyResources() throws IOException {

        //pull generator and agency logos from branding
        String generatorLogoPath = reportBranding.getGeneratorLogoPath();
        if (StringUtils.isNotBlank(generatorLogoPath)) {
            Files.copy(Files.newInputStream(Paths.get(generatorLogoPath)),
                    reportFolderPath.resolve("generator_logo.png")); //NON-NLS
        }
        String agencyLogoPath = reportBranding.getAgencyLogoPath();
        if (StringUtils.isNotBlank(agencyLogoPath)) {
            Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)),
                    reportFolderPath.resolve("agency_logo.png")); //NON-NLS
        }

        //copy navigation html
        try (InputStream navStream = SnapShotReportWriter.class
                .getResourceAsStream("/org/sleuthkit/autopsy/timeline/snapshot/navigation.html")) { //NON-NLS
            Files.copy(navStream, reportFolderPath.resolve("nav.html")); //NON-NLS
        }
        //copy favicon
        if (StringUtils.isBlank(agencyLogoPath)) {
            // use default Autopsy icon if custom icon is not set
            try (InputStream faviconStream = SnapShotReportWriter.class
                    .getResourceAsStream("/org/sleuthkit/autopsy/report/images/favicon.ico")) { //NON-NLS
                Files.copy(faviconStream, reportFolderPath.resolve("favicon.ico")); //NON-NLS
            }
        } else {
            Files.copy(Files.newInputStream(Paths.get(agencyLogoPath)), reportFolderPath.resolve("favicon.ico")); //NON-NLS           
        }

        //copy report summary icon
        try (InputStream summaryStream = SnapShotReportWriter.class
                .getResourceAsStream("/org/sleuthkit/autopsy/report/images/summary.png")) { //NON-NLS
            Files.copy(summaryStream, reportFolderPath.resolve("summary.png")); //NON-NLS
        }
        //copy snapshot icon
        try (InputStream snapshotIconStream = SnapShotReportWriter.class
                .getResourceAsStream("/org/sleuthkit/autopsy/timeline/images/image.png")) { //NON-NLS
            Files.copy(snapshotIconStream, reportFolderPath.resolve("snapshot_icon.png")); //NON-NLS
        }
        //copy main report css
        try (InputStream resource = SnapShotReportWriter.class
                .getResourceAsStream("/org/sleuthkit/autopsy/timeline/snapshot/index.css")) { //NON-NLS
            Files.copy(resource, reportFolderPath.resolve("index.css")); //NON-NLS
        }
        //copy summary css
        try (InputStream resource = SnapShotReportWriter.class
                .getResourceAsStream("/org/sleuthkit/autopsy/timeline/snapshot/summary.css")) { //NON-NLS
            Files.copy(resource, reportFolderPath.resolve("summary.css")); //NON-NLS
        }
    }
}