org.sleuthkit.autopsy.thunderbirdparser.ThunderbirdMboxFileIngestService.java Source code

Java tutorial

Introduction

Here is the source code for org.sleuthkit.autopsy.thunderbirdparser.ThunderbirdMboxFileIngestService.java

Source

/*
 * Autopsy Forensic Browser
 *
 * Copyright 2011 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.thunderbirdparser;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.apache.tika.exception.TikaException;
import org.apache.tika.metadata.Metadata;
import org.sleuthkit.autopsy.ingest.IngestManager;
import org.sleuthkit.autopsy.ingest.IngestManagerProxy;
import org.sleuthkit.autopsy.ingest.IngestMessage;
import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType;
import org.sleuthkit.autopsy.ingest.IngestServiceAbstract.*;
import org.sleuthkit.autopsy.ingest.IngestServiceAbstractFile;
import org.sleuthkit.autopsy.ingest.ServiceDataEvent;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.ReadContentInputStream;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
import org.xml.sax.SAXException;
import org.apache.commons.lang.StringEscapeUtils;
import org.sleuthkit.autopsy.casemodule.Case;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;

public class ThunderbirdMboxFileIngestService implements IngestServiceAbstractFile {

    private static final Logger logger = Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName());
    private static ThunderbirdMboxFileIngestService instance = null;
    private IngestManagerProxy managerProxy;
    private static int messageId = 0;
    private static final String classname = "Thunderbird Parser";
    private final String hashDBServiceName = "Hash Lookup";

    public static synchronized ThunderbirdMboxFileIngestService getDefault() {
        if (instance == null) {
            instance = new ThunderbirdMboxFileIngestService();
        }
        return instance;
    }

    @Override
    public ProcessResult process(AbstractFile fsContent) {
        ThunderbirdEmailParser mbox = new ThunderbirdEmailParser();
        boolean isMbox = false;

        IngestServiceAbstractFile.ProcessResult hashDBResult = managerProxy
                .getAbstractFileServiceResult(hashDBServiceName);

        if (hashDBResult == IngestServiceAbstractFile.ProcessResult.COND_STOP) {
            return ProcessResult.OK; //file is known, stop processing it
        } else if (hashDBResult == IngestServiceAbstractFile.ProcessResult.ERROR) {
            return ProcessResult.ERROR; //file has read error, stop processing it
        }

        try {
            byte[] t = new byte[64];
            if (fsContent.getSize() > 64) {
                int byteRead = fsContent.read(t, 0, 64);
                isMbox = mbox.isValidMimeTypeMbox(t);
            }
        } catch (TskException ex) {
            Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
        }

        if (isMbox) {
            managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this,
                    "Processing " + fsContent.getName()));
            String mboxName = fsContent.getName();
            String msfName = mboxName + ".msf";
            Long mboxId = fsContent.getId();
            String mboxPath = "";
            Long msfId = 0L;
            Case currentCase = Case.getCurrentCase(); // get the most updated case
            SleuthkitCase tskCase = currentCase.getSleuthkitCase();
            try {
                ResultSet rs = tskCase
                        .runQuery("select parent_path from tsk_files where obj_id = '" + mboxId.toString() + "'");
                mboxPath = rs.getString("parent_path");
                Statement s = rs.getStatement();
                rs.close();
                if (s != null) {
                    s.close();
                }
                rs.close();
                rs.getStatement().close();

                ResultSet resultset = tskCase.runQuery("select obj_id from tsk_files where parent_path = '"
                        + mboxPath + "' and name = '" + msfName + "'");
                msfId = resultset.getLong("obj_id");
                Statement st = resultset.getStatement();
                resultset.close();
                if (st != null) {
                    st.close();
                }
                resultset.close();
                resultset.getStatement().close();

            } catch (SQLException ex) {
                logger.log(Level.WARNING, "Error while trying to get parent path for:" + this.getClass().getName(),
                        ex);
            }

            try {
                Content msfContent = tskCase.getContentById(msfId);
                ContentUtils.writeToFile(msfContent,
                        new File(currentCase.getTempDirectory() + File.separator + msfName));
            } catch (IOException ex) {
                Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
            } catch (TskCoreException ex) {
                logger.log(Level.WARNING, "Unable to obtain msf file for mbox parsing:" + this.getClass().getName(),
                        ex);
            }
            int index = 0;
            String replace = "";
            boolean a = mboxPath.indexOf("/ImapMail/") > 0;
            boolean b = mboxPath.indexOf("/Mail/") > 0;
            if (b == true) {
                index = mboxPath.indexOf("/Mail/");
                replace = "/Mail";
            } else if (a == true) {
                index = mboxPath.indexOf("/ImapMail/");
                replace = "/ImapMail";
            } else {
                replace = "";

            }
            String folderPath = mboxPath.substring(index);
            folderPath = folderPath.replaceAll(replace, "");
            folderPath = folderPath + mboxName;
            folderPath = folderPath.replaceAll(".sbd", "");
            //            Reader reader = null;
            //            try {
            //                reader = new FileReader(currentCase.getTempDirectory() + File.separator + msfName);
            //            } catch (FileNotFoundException ex) {
            //                Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
            //            }
            //            MorkDocument morkDocument = new MorkDocument(reader);
            //            List<Dict> dicts = morkDocument.getDicts();
            //            for(Dict dict : dicts){
            //            String path = dict.getValue("81").toString();
            //             String account = dict.getValue("8D").toString();
            //                    }
            String emailId = "";
            String content = "";
            String from = "";
            String to = "";
            String stringDate = "";
            Long date = 0L;
            String subject = "";
            String cc = "";
            String bcc = "";
            try {
                ReadContentInputStream contentStream = new ReadContentInputStream(fsContent);
                mbox.parse(contentStream);
                HashMap<String, Map<String, String>> emailMap = new HashMap<String, Map<String, String>>();
                emailMap = mbox.getAllEmails();
                for (Entry<String, Map<String, String>> entry : emailMap.entrySet()) {
                    Map<String, String> propertyMap = new HashMap<String, String>();
                    emailId = ((entry.getKey() != null) ? entry.getKey() : "Not Available");
                    propertyMap = entry.getValue();
                    content = ((propertyMap.get("content") != null) ? propertyMap.get("content") : "");
                    from = ((propertyMap.get(Metadata.AUTHOR) != null) ? propertyMap.get(Metadata.AUTHOR) : "");
                    to = ((propertyMap.get(Metadata.MESSAGE_TO) != null) ? propertyMap.get(Metadata.MESSAGE_TO)
                            : "");
                    stringDate = ((propertyMap.get("date") != null) ? propertyMap.get("date") : "");
                    if (!"".equals(stringDate)) {
                        date = mbox.getDateCreated(stringDate);
                    }
                    subject = ((propertyMap.get(Metadata.SUBJECT) != null) ? propertyMap.get(Metadata.SUBJECT)
                            : "");
                    cc = ((propertyMap.get(Metadata.MESSAGE_CC) != null) ? propertyMap.get(Metadata.MESSAGE_CC)
                            : "");
                    bcc = ((propertyMap.get(Metadata.MESSAGE_BCC) != null) ? propertyMap.get(Metadata.MESSAGE_BCC)
                            : "");

                    Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
                    bbattributes.add(
                            new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_TO.getTypeID(), classname, "", to));
                    bbattributes.add(
                            new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CC.getTypeID(), classname, "", cc));
                    bbattributes.add(
                            new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_BCC.getTypeID(), classname, "", bcc));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_FROM.getTypeID(), classname,
                            "", from));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_PLAIN.getTypeID(),
                            classname, "", content.replaceAll("\\<[^>]*>", "")));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID(),
                            classname, "", content));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), classname, "",
                            StringEscapeUtils.escapeHtml(emailId)));
                    //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MSG_REPLY_ID.getTypeID(), classname, "",));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_RCVD.getTypeID(),
                            classname, "", date));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_SENT.getTypeID(),
                            classname, "", date));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_SUBJECT.getTypeID(), classname, "",
                            subject));
                    bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), classname, "",
                            folderPath));
                    BlackboardArtifact bbart;
                    try {
                        bbart = fsContent.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG);
                        bbart.addAttributes(bbattributes);
                    } catch (TskCoreException ex) {
                        Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null,
                                ex);
                    }
                    IngestManagerProxy.fireServiceDataEvent(
                            new ServiceDataEvent(classname, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG));
                }
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
            } catch (SAXException ex) {
                Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
            } catch (TikaException ex) {
                Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.WARNING, null, ex);
            }
        }

        return ProcessResult.OK;
    }

    @Override
    public void complete() {
        logger.log(Level.INFO, "complete()");
        managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "COMPLETE"));

        //service specific cleanup due completion here
    }

    @Override
    public String getName() {
        return "Thunderbird Parser";
    }

    @Override
    public String getDescription() {
        return "This class parses through a file to determine if it is an mbox file and if so, populates an email artifact for it in the blackboard.";
    }

    @Override
    public void init(IngestManagerProxy managerProxy) {
        logger.log(Level.INFO, "init()");
        this.managerProxy = managerProxy;

        //service specific initialization here
    }

    @Override
    public void stop() {
        logger.log(Level.INFO, "stop()");

        //service specific cleanup due interruption here
    }

    @Override
    public ServiceType getType() {
        return ServiceType.AbstractFile;
    }

    @Override
    public boolean hasSimpleConfiguration() {
        return false;
    }

    @Override
    public boolean hasAdvancedConfiguration() {
        return false;
    }

    @Override
    public javax.swing.JPanel getSimpleConfiguration() {
        return null;
    }

    @Override
    public javax.swing.JPanel getAdvancedConfiguration() {
        return null;
    }

    @Override
    public boolean hasBackgroundJobsRunning() {
        return false;
    }

    @Override
    public void saveAdvancedConfiguration() {
    }

    @Override
    public void saveSimpleConfiguration() {
    }
}