diff --git a/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties b/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties index 894d3989db..0b28aee69e 100644 --- a/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties +++ b/CoreUtils/src/org/sleuthkit/autopsy/coreutils/Bundle.properties @@ -1,8 +1,8 @@ #Updated by build script -#Thu, 07 Jun 2012 13:38:12 -0700 +#Mon, 18 Jun 2012 14:35:03 -0700 OpenIDE-Module-Name=CoreUtils app.name=Autopsy -app.version=20120607 +app.version=20120618 build.type=DEVELOPMENT diff --git a/MboxEmailModule/manifest.mf b/MboxEmailModule/manifest.mf deleted file mode 100644 index ab1f5c0657..0000000000 --- a/MboxEmailModule/manifest.mf +++ /dev/null @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: org.sleuthkit.autopsy.mboxparser -OpenIDE-Module-Layer: org/sleuthkit/autopsy/mboxparser/layer.xml -OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/mboxparser/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff --git a/MboxEmailModule/nbproject/project.xml b/MboxEmailModule/nbproject/project.xml deleted file mode 100644 index e897b3d39f..0000000000 --- a/MboxEmailModule/nbproject/project.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - org.netbeans.modules.apisupport.project - - - org.sleuthkit.autopsy.mboxparser - - - - org.sleuthkit.autopsy.casemodule - - - - 1 - 1.0 - - - - org.sleuthkit.autopsy.coreutils - - - - 0-1 - 0.0 - - - - org.sleuthkit.autopsy.datamodel - - - - 1 - 1.0 - - - - org.sleuthkit.autopsy.ingest - - - - 0-1 - 1.0 - - - - - - ext/tika-core-1.1.jar - release/modules/ext/tika-core-1.1.jar - - - ext/tika-parsers-1.1.jar - release/modules/ext/tika-parsers-1.1.jar - - - - diff --git a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/Bundle.properties b/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/Bundle.properties deleted file mode 100644 index b852096925..0000000000 --- a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/Bundle.properties +++ /dev/null @@ -1 +0,0 @@ -OpenIDE-Module-Name=MboxEmailModule diff --git a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/MboxEmailParser.java b/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/MboxEmailParser.java deleted file mode 100644 index 898781b4fa..0000000000 --- a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/MboxEmailParser.java +++ /dev/null @@ -1,206 +0,0 @@ -package org.sleuthkit.autopsy.mboxparser; - -import java.io.*; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.tika.Tika; -import org.apache.tika.exception.TikaException; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.mime.MimeTypes; -import org.apache.tika.mime.MediaType; -import org.apache.tika.parser.ParseContext; -import org.apache.tika.parser.Parser; -import org.apache.tika.parser.mbox.MboxParser; -import org.apache.tika.sax.BodyContentHandler; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - -public class MboxEmailParser { - - - private InputStream stream; - //Tika object - private Tika tika; - private Metadata metadata; - private ContentHandler contentHandler; - private String mimeType; - private Parser parser; - private ParseContext context; - - private static ArrayList tikaMimeTypes; - - static - { - tikaMimeTypes = new ArrayList(); - tikaMimeTypes.add(MimeTypes.OCTET_STREAM); - tikaMimeTypes.add(MimeTypes.PLAIN_TEXT); - tikaMimeTypes.add(MimeTypes.XML); - } - - public MboxEmailParser() - { - this.tika = new Tika(); - } - - public MboxEmailParser(InputStream inStream) - { - this.tika = new Tika(); - this.stream = inStream; - } - - public MboxEmailParser(String filepath) - { - this.tika = new Tika(); - this.stream = this.getClass().getResourceAsStream(filepath); - } - - private void init() throws IOException - { - this.tika.setMaxStringLength(10*1024*1024); - this.metadata = new Metadata(); - //Set MIME Type - this.mimeType = tika.detect(this.stream); - this.parser = new MboxParser(); - this.context = new ParseContext(); - - this.contentHandler = new BodyContentHandler(-1); - //Seems like setting this causes the metadata not to output all of it. - // this.metadata.set(Metadata.CONTENT_TYPE, this.mimeType); - } - - public void parse() throws FileNotFoundException, IOException, SAXException, TikaException - { - init(); - // this.metadata = new Metadata(); - //String mimeType = tika.detect(this.stream); - parser.parse(this.stream,this.contentHandler, this.metadata, context); - } - - public void parse(InputStream inStream) throws FileNotFoundException, IOException, SAXException, TikaException - { - init(); - parser.parse(inStream,this.contentHandler, this.metadata, context); - String blbha = "stop"; - } - - public Metadata getMetadata() - { - return this.metadata; - } - - - //Returns message content, i.e. plain text or html - public String getContent() - { - return this.contentHandler.toString(); - } - - public String detectEmailFileFormat(String filepath) throws IOException - { - return this.tika.detect(filepath); - } - - //Detects the mime type from the first few bytes of the document - public String detectMediaTypeFromBytes(byte[] firstFewBytes, String inDocName) - { - return this.tika.detect(firstFewBytes, inDocName); - } - - - public boolean isValidMimeTypeMbox(byte[] buffer) - { - return (new String(buffer)).startsWith("From "); - } - - //This assumes the file/stream was parsed since we are looking at the metadata - public boolean isValidMboxType() - { - return this.metadata.get(Metadata.CONTENT_TYPE).equals("application/mbox"); - } - - //Get email subject - public String getSubject() - { - return this.metadata.get(Metadata.SUBJECT); - } - - public String getTitle() - { - return this.metadata.get(Metadata.TITLE); - } - - public Long getDateCreated() - { - Long epochtime; - Long ftime = (long) 0; - - try { - String datetime = this.metadata.get(Metadata.DATE); - epochtime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(datetime).getTime(); - ftime = epochtime.longValue(); - ftime = ftime / 1000; - } catch (ParseException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } - - return ftime; - } - - public String getApplication() - { - String client; - String userAgent = ""; - userAgent = this.metadata.get("MboxParser-user-agent"); - if(userAgent.matches("(?i).*Thunderbird.*")) - { - client = "Thunderbird"; - } - else{ - client = "Unknown"; - } - return client; - } - - public String getContenType() - { - return this.metadata.get(Metadata.CONTENT_TYPE); - } - - public String getContenEncoding() - { - return this.metadata.get(Metadata.CONTENT_ENCODING); - } - - public String getFrom() - { - return this.metadata.get(Metadata.AUTHOR); - } - - public String getTo() - { - return this.metadata.get(Metadata.MESSAGE_TO); - } - - public String getCC() - { - return this.metadata.get(Metadata.MESSAGE_CC); - } - - public String getBCC() - { - return this.metadata.get(Metadata.MESSAGE_BCC); - } - - public String getRecipientAddress() - { - return this.metadata.get(Metadata.MESSAGE_RECIPIENT_ADDRESS); - } - - public String getMboxSupportedMediaType() - { - return MediaType.application("mbox").getType(); - } -} diff --git a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/MboxFileIngestService.java b/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/MboxFileIngestService.java deleted file mode 100644 index e8993058dd..0000000000 --- a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/MboxFileIngestService.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.mboxparser; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.tika.exception.TikaException; -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.BlackboardArtifact.ARTIFACT_TYPE; -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; - -public class MboxFileIngestService implements IngestServiceAbstractFile { - - private static final Logger logger = Logger.getLogger(MboxFileIngestService.class.getName()); - private static MboxFileIngestService instance = null; - private IngestManagerProxy managerProxy; - private static int messageId = 0; - private static final String classname = "Mbox Parser"; - - public static synchronized MboxFileIngestService getDefault() { - if (instance == null) { - instance = new MboxFileIngestService(); - } - return instance; - } - - @Override - public ProcessResult process(AbstractFile fsContent) { - MboxEmailParser mbox = new MboxEmailParser(); - boolean isMbox = false; - - try { - byte[] t = new byte[(int) 128]; - int byteRead = fsContent.read(t, 0, 128); - isMbox = mbox.isValidMimeTypeMbox(t); - } catch (TskException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } - - - if (isMbox) { - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName())); - try { - ReadContentInputStream contentStream = new ReadContentInputStream(fsContent); - mbox.parse(contentStream); - String content = mbox.getContent(); - String client = mbox.getApplication(); - String from = mbox.getFrom(); - String to = mbox.getTo(); - Long date = mbox.getDateCreated(); - String subject = mbox.getSubject(); - String cc = mbox.getCC(); - String bcc = mbox.getBCC(); - Collection bbattributes = new ArrayList(); - 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)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID(), classname, "", content)); - //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), classname, "",)); - //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_PROG_NAME.getTypeID(), classname, "", client)); - BlackboardArtifact bbart; - try { - bbart = fsContent.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG); - bbart.addAttributes(bbattributes); - } catch (TskCoreException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } - - - - IngestManager.fireServiceDataEvent(new ServiceDataEvent(classname, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG)); - } catch (FileNotFoundException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } catch (SAXException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } catch (TikaException ex) { - Logger.getLogger(MboxFileIngestService.class.getName()).log(Level.SEVERE, 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 "Mbox 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() { - } -} \ No newline at end of file diff --git a/Report/nbproject/genfiles.properties b/Report/nbproject/genfiles.properties index 7018d67bfa..b3954a5498 100644 --- a/Report/nbproject/genfiles.properties +++ b/Report/nbproject/genfiles.properties @@ -1,8 +1,8 @@ -build.xml.data.CRC32=d23c11ef +build.xml.data.CRC32=d1b02431 build.xml.script.CRC32=bbb1c310 build.xml.stylesheet.CRC32=a56c6a5b@1.46.2 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. -nbproject/build-impl.xml.data.CRC32=d23c11ef +nbproject/build-impl.xml.data.CRC32=d1b02431 nbproject/build-impl.xml.script.CRC32=1562aec2 nbproject/build-impl.xml.stylesheet.CRC32=238281d1@1.46.2 diff --git a/ThunderbirdMboxEmailModule/build.xml b/ThunderbirdMboxEmailModule/build.xml deleted file mode 100644 index 610fee55de..0000000000 --- a/ThunderbirdMboxEmailModule/build.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - Builds, tests, and runs the project org.sleuthkit.autopsy.mboxparser. - - diff --git a/ThunderbirdMboxEmailModule/manifest.mf b/ThunderbirdMboxEmailModule/manifest.mf deleted file mode 100644 index ce08e338cd..0000000000 --- a/ThunderbirdMboxEmailModule/manifest.mf +++ /dev/null @@ -1,6 +0,0 @@ -Manifest-Version: 1.0 -OpenIDE-Module: org.sleuthkit.autopsy.mboxparser -OpenIDE-Module-Layer: org/sleuthkit/autopsy/mboxparser/layer.xml -OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/mboxparser/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 - diff --git a/ThunderbirdMboxEmailModule/nbproject/build-impl.xml b/ThunderbirdMboxEmailModule/nbproject/build-impl.xml deleted file mode 100644 index 445bd74ba3..0000000000 --- a/ThunderbirdMboxEmailModule/nbproject/build-impl.xml +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - - - - - - You must set 'suite.dir' to point to your containing module suite - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ThunderbirdMboxEmailModule/nbproject/platform.properties b/ThunderbirdMboxEmailModule/nbproject/platform.properties deleted file mode 100644 index 1d9ac9bcfa..0000000000 --- a/ThunderbirdMboxEmailModule/nbproject/platform.properties +++ /dev/null @@ -1,100 +0,0 @@ -cluster.path=\ - ${nbplatform.active.dir}/harness:\ - ${nbplatform.active.dir}/java:\ - ${nbplatform.active.dir}/platform -disabled.modules=\ - org.apache.tools.ant.module,\ - org.netbeans.api.debugger.jpda,\ - org.netbeans.api.java,\ - org.netbeans.libs.cglib,\ - org.netbeans.libs.javacapi,\ - org.netbeans.libs.javacimpl,\ - org.netbeans.libs.jsr223,\ - org.netbeans.libs.springframework,\ - org.netbeans.modules.ant.browsetask,\ - org.netbeans.modules.ant.debugger,\ - org.netbeans.modules.ant.freeform,\ - org.netbeans.modules.ant.grammar,\ - org.netbeans.modules.ant.kit,\ - org.netbeans.modules.beans,\ - org.netbeans.modules.classfile,\ - org.netbeans.modules.dbschema,\ - org.netbeans.modules.debugger.jpda,\ - org.netbeans.modules.debugger.jpda.ant,\ - org.netbeans.modules.debugger.jpda.projects,\ - org.netbeans.modules.debugger.jpda.ui,\ - org.netbeans.modules.form,\ - org.netbeans.modules.form.j2ee,\ - org.netbeans.modules.form.kit,\ - org.netbeans.modules.hibernate,\ - org.netbeans.modules.hibernatelib,\ - org.netbeans.modules.hudson.ant,\ - org.netbeans.modules.hudson.maven,\ - org.netbeans.modules.i18n,\ - org.netbeans.modules.i18n.form,\ - org.netbeans.modules.j2ee.core.utilities,\ - org.netbeans.modules.j2ee.eclipselink,\ - org.netbeans.modules.j2ee.eclipselinkmodelgen,\ - org.netbeans.modules.j2ee.jpa.refactoring,\ - org.netbeans.modules.j2ee.jpa.verification,\ - org.netbeans.modules.j2ee.metadata,\ - org.netbeans.modules.j2ee.metadata.model.support,\ - org.netbeans.modules.j2ee.persistence,\ - org.netbeans.modules.j2ee.persistence.kit,\ - org.netbeans.modules.j2ee.persistenceapi,\ - org.netbeans.modules.j2ee.toplinklib,\ - org.netbeans.modules.java.api.common,\ - org.netbeans.modules.java.debug,\ - org.netbeans.modules.java.editor,\ - org.netbeans.modules.java.editor.lib,\ - org.netbeans.modules.java.examples,\ - org.netbeans.modules.java.freeform,\ - org.netbeans.modules.java.guards,\ - org.netbeans.modules.java.helpset,\ - org.netbeans.modules.java.hints,\ - org.netbeans.modules.java.hints.processor,\ - org.netbeans.modules.java.j2seplatform,\ - org.netbeans.modules.java.j2seproject,\ - org.netbeans.modules.java.kit,\ - org.netbeans.modules.java.lexer,\ - org.netbeans.modules.java.navigation,\ - org.netbeans.modules.java.platform,\ - org.netbeans.modules.java.preprocessorbridge,\ - org.netbeans.modules.java.project,\ - org.netbeans.modules.java.source,\ - org.netbeans.modules.java.source.ant,\ - org.netbeans.modules.java.sourceui,\ - org.netbeans.modules.javadoc,\ - org.netbeans.modules.javawebstart,\ - org.netbeans.modules.jellytools,\ - org.netbeans.modules.jellytools.java,\ - org.netbeans.modules.junit,\ - org.netbeans.modules.maven,\ - org.netbeans.modules.maven.coverage,\ - org.netbeans.modules.maven.embedder,\ - org.netbeans.modules.maven.grammar,\ - org.netbeans.modules.maven.graph,\ - org.netbeans.modules.maven.hints,\ - org.netbeans.modules.maven.indexer,\ - org.netbeans.modules.maven.junit,\ - org.netbeans.modules.maven.kit,\ - org.netbeans.modules.maven.model,\ - org.netbeans.modules.maven.osgi,\ - org.netbeans.modules.maven.persistence,\ - org.netbeans.modules.maven.repository,\ - org.netbeans.modules.maven.search,\ - org.netbeans.modules.maven.spring,\ - org.netbeans.modules.projectimport.eclipse.core,\ - org.netbeans.modules.projectimport.eclipse.j2se,\ - org.netbeans.modules.refactoring.java,\ - org.netbeans.modules.spellchecker.bindings.java,\ - org.netbeans.modules.spring.beans,\ - org.netbeans.modules.swingapp,\ - org.netbeans.modules.websvc.jaxws21,\ - org.netbeans.modules.websvc.jaxws21api,\ - org.netbeans.modules.websvc.saas.codegen.java,\ - org.netbeans.modules.xml.jaxb,\ - org.netbeans.modules.xml.tools.java,\ - org.openide.compat,\ - org.openide.util.enumerations -nbplatform.active=default diff --git a/ThunderbirdMboxEmailModule/nbproject/project.properties b/ThunderbirdMboxEmailModule/nbproject/project.properties deleted file mode 100644 index 4b781ec33c..0000000000 --- a/ThunderbirdMboxEmailModule/nbproject/project.properties +++ /dev/null @@ -1,2 +0,0 @@ -javac.source=1.6 -javac.compilerargs=-Xlint -Xlint:-serial diff --git a/ThunderbirdMboxEmailModule/nbproject/suite.properties b/ThunderbirdMboxEmailModule/nbproject/suite.properties deleted file mode 100644 index 364e160e16..0000000000 --- a/ThunderbirdMboxEmailModule/nbproject/suite.properties +++ /dev/null @@ -1 +0,0 @@ -suite.dir=${basedir}/.. diff --git a/ThunderbirdMboxEmailModule/release/modules/ext/tika-core-1.1.jar b/ThunderbirdMboxEmailModule/release/modules/ext/tika-core-1.1.jar deleted file mode 100644 index 7ad2be62be..0000000000 Binary files a/ThunderbirdMboxEmailModule/release/modules/ext/tika-core-1.1.jar and /dev/null differ diff --git a/ThunderbirdMboxEmailModule/release/modules/ext/tika-parsers-1.1.jar b/ThunderbirdMboxEmailModule/release/modules/ext/tika-parsers-1.1.jar deleted file mode 100644 index ad82942ae3..0000000000 Binary files a/ThunderbirdMboxEmailModule/release/modules/ext/tika-parsers-1.1.jar and /dev/null differ diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties b/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties deleted file mode 100644 index ce7758f02d..0000000000 --- a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties +++ /dev/null @@ -1 +0,0 @@ -OpenIDE-Module-Name=ThunderbirdMboxEmailModule diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/layer.xml b/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/layer.xml deleted file mode 100644 index 6d26e34fd2..0000000000 --- a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/layer.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/nbproject/project.properties b/nbproject/project.properties index db59b37267..abdda11faf 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -30,7 +30,7 @@ modules=\ ${project.org.sleuthkit.autopsy.recentactivity}:\ ${project.org.sleuthkit.autopsy.report}:\ ${project.org.sleuthkit.autopsy.testing}:\ - ${project.org.sleuthkit.autopsy.mboxparser} + ${project.org.sleuthkit.autopsy.thunderbirdparser} project.org.sleuthkit.autopsy.casemodule=Case project.org.sleuthkit.autopsy.corecomponentinterfaces=CoreComponentInterfaces project.org.sleuthkit.autopsy.corecomponents=CoreComponents @@ -40,10 +40,10 @@ project.org.sleuthkit.autopsy.filesearch=FileSearch project.org.sleuthkit.autopsy.hashdatabase=HashDatabase project.org.sleuthkit.autopsy.ingest=Ingest project.org.sleuthkit.autopsy.keywordsearch=KeywordSearch -project.org.sleuthkit.autopsy.mboxparser=MboxEmailModule project.org.sleuthkit.autopsy.menuactions=MenuActions project.org.sleuthkit.autopsy.datamodel=DataModel project.org.sleuthkit.autopsy.recentactivity=RecentActivity project.org.sleuthkit.autopsy.report=Report project.org.sleuthkit.autopsy.testing=Testing +project.org.sleuthkit.autopsy.thunderbirdparser=thunderbirdparser diff --git a/MboxEmailModule/build.xml b/thunderbirdparser/build.xml similarity index 75% rename from MboxEmailModule/build.xml rename to thunderbirdparser/build.xml index 839c55209b..c6442bd82f 100644 --- a/MboxEmailModule/build.xml +++ b/thunderbirdparser/build.xml @@ -2,7 +2,7 @@ - - Builds, tests, and runs the project org.sleuthkit.autopsy.mboxparser. + + Builds, tests, and runs the project org.sleuthkit.autopsy.thunderbirdparser. diff --git a/thunderbirdparser/manifest.mf b/thunderbirdparser/manifest.mf new file mode 100644 index 0000000000..d7eac29b01 --- /dev/null +++ b/thunderbirdparser/manifest.mf @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: org.sleuthkit.autopsy.thunderbirdparser +OpenIDE-Module-Layer: org/sleuthkit/autopsy/thunderbirdparser/layer.xml +OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff --git a/MboxEmailModule/nbproject/build-impl.xml b/thunderbirdparser/nbproject/build-impl.xml similarity index 96% rename from MboxEmailModule/nbproject/build-impl.xml rename to thunderbirdparser/nbproject/build-impl.xml index ceafc8e5e3..aede86239b 100644 --- a/MboxEmailModule/nbproject/build-impl.xml +++ b/thunderbirdparser/nbproject/build-impl.xml @@ -3,7 +3,7 @@ *** GENERATED FROM project.xml - DO NOT EDIT *** *** EDIT ../build.xml INSTEAD *** --> - + diff --git a/MboxEmailModule/nbproject/project.properties b/thunderbirdparser/nbproject/project.properties similarity index 100% rename from MboxEmailModule/nbproject/project.properties rename to thunderbirdparser/nbproject/project.properties diff --git a/ThunderbirdMboxEmailModule/nbproject/project.xml b/thunderbirdparser/nbproject/project.xml similarity index 85% rename from ThunderbirdMboxEmailModule/nbproject/project.xml rename to thunderbirdparser/nbproject/project.xml index 2bb3a3a429..b63547d097 100644 --- a/ThunderbirdMboxEmailModule/nbproject/project.xml +++ b/thunderbirdparser/nbproject/project.xml @@ -1,57 +1,65 @@ - - - org.netbeans.modules.apisupport.project - - - org.sleuthkit.autopsy.mboxparser - - - - org.sleuthkit.autopsy.casemodule - - - - 1 - 1.0 - - - - org.sleuthkit.autopsy.coreutils - - - - 0-1 - 0.0 - - - - org.sleuthkit.autopsy.datamodel - - - - 1 - 1.0 - - - - org.sleuthkit.autopsy.ingest - - - - 0-1 - 1.0 - - - - - - ext/tika-core-1.1.jar - release/modules/ext/tika-core-1.1.jar - - - ext/tika-parsers-1.1.jar - release/modules/ext/tika-parsers-1.1.jar - - - - + + + org.netbeans.modules.apisupport.project + + + org.sleuthkit.autopsy.thunderbirdparser + + + + org.sleuthkit.autopsy.casemodule + + + + 1 + 1.0 + + + + org.sleuthkit.autopsy.coreutils + + + + 0-1 + 0.0 + + + + org.sleuthkit.autopsy.datamodel + + + + 1 + 1.0 + + + + org.sleuthkit.autopsy.ingest + + + + 0-1 + 1.0 + + + + org.sleuthkit.autopsy.recentactivity + + + + 1.0 + + + + + + ext/tika-core-1.1.jar + release/modules/ext/tika-core-1.1.jar + + + ext/tika-parsers-1.1.jar + release/modules/ext/tika-parsers-1.1.jar + + + + diff --git a/MboxEmailModule/nbproject/suite.properties b/thunderbirdparser/nbproject/suite.properties similarity index 100% rename from MboxEmailModule/nbproject/suite.properties rename to thunderbirdparser/nbproject/suite.properties diff --git a/MboxEmailModule/release/modules/ext/tika-core-1.1.jar b/thunderbirdparser/release/modules/ext/tika-core-1.1.jar similarity index 100% rename from MboxEmailModule/release/modules/ext/tika-core-1.1.jar rename to thunderbirdparser/release/modules/ext/tika-core-1.1.jar diff --git a/MboxEmailModule/release/modules/ext/tika-parsers-1.1.jar b/thunderbirdparser/release/modules/ext/tika-parsers-1.1.jar similarity index 100% rename from MboxEmailModule/release/modules/ext/tika-parsers-1.1.jar rename to thunderbirdparser/release/modules/ext/tika-parsers-1.1.jar diff --git a/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties new file mode 100644 index 0000000000..c5b290dd76 --- /dev/null +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/Bundle.properties @@ -0,0 +1 @@ +OpenIDE-Module-Name=ThunderbirdParser diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdEmailParser.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdEmailParser.java similarity index 95% rename from ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdEmailParser.java rename to thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdEmailParser.java index 45c7e66029..5974f4c076 100644 --- a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdEmailParser.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdEmailParser.java @@ -1,183 +1,183 @@ -package org.sleuthkit.autopsy.thunderbirdparser; - -import java.io.*; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.tika.Tika; -import org.apache.tika.exception.TikaException; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.mime.MimeTypes; -import org.apache.tika.mime.MediaType; -import org.apache.tika.parser.ParseContext; -import org.apache.tika.sax.BodyContentHandler; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - -public class ThunderbirdEmailParser { - - - private InputStream stream; - //Tika object - private Tika tika; - private ThunderbirdMetadata metadata; - private ContentHandler contentHandler; - private String mimeType; - private ThunderbirdMboxParser parser; - private ParseContext context; - - private static ArrayList tikaMimeTypes; - - static - { - tikaMimeTypes = new ArrayList(); - tikaMimeTypes.add(MimeTypes.OCTET_STREAM); - tikaMimeTypes.add(MimeTypes.PLAIN_TEXT); - tikaMimeTypes.add(MimeTypes.XML); - } - - public ThunderbirdEmailParser() - { - this.tika = new Tika(); - } - - public ThunderbirdEmailParser(InputStream inStream) - { - this.tika = new Tika(); - this.stream = inStream; - } - - public ThunderbirdEmailParser(String filepath) - { - this.tika = new Tika(); - this.stream = this.getClass().getResourceAsStream(filepath); - } - - private void init() throws IOException - { - this.tika.setMaxStringLength(10*1024*1024); - this.metadata = new ThunderbirdMetadata(); - //Set MIME Type - //this.mimeType = tika.detect(this.stream); - this.parser = new ThunderbirdMboxParser(); - this.context = new ParseContext(); - this.contentHandler = new BodyContentHandler(10*1024*1024); - } - - public void parse() throws FileNotFoundException, IOException, SAXException, TikaException - { - init(); - parser.parse(this.stream,this.contentHandler, this.metadata, context); - } - - public void parse(InputStream inStream) throws FileNotFoundException, IOException, SAXException, TikaException - { - init(); - parser.parse(inStream,this.contentHandler, this.metadata, context); - } - - public ThunderbirdMetadata getMetadata() - { - return this.metadata; - } - - - //Returns message content, i.e. plain text or html - public String getContent() - { - return this.contentHandler.toString(); - } - - public String detectEmailFileFormat(String filepath) throws IOException - { - return this.tika.detect(filepath); - } - - //Detects the mime type from the first few bytes of the document - public String detectMediaTypeFromBytes(byte[] firstFewBytes, String inDocName) - { - return this.tika.detect(firstFewBytes, inDocName); - } - - - public boolean isValidMimeTypeMbox(byte[] buffer) - { - return (new String(buffer)).startsWith("From "); - } - - //This assumes the file/stream was parsed since we are looking at the metadata - public boolean isValidMboxType() - { - return this.metadata.get(Metadata.CONTENT_TYPE).equals("application/mbox"); - } - - //Get email subject - public String getSubject() - { - return this.metadata.get(Metadata.SUBJECT); - } - - public String getTitle() - { - return this.metadata.get(Metadata.TITLE); - } - - public Long getDateCreated() - { - Long epochtime; - Long ftime = 0L; - - try { - String datetime = this.metadata.get(Metadata.DATE); - epochtime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(datetime).getTime(); - ftime = epochtime.longValue(); - ftime = ftime / 1000; - } catch (ParseException ex) { - Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } - - return ftime; - } - - public String getContenType() - { - return this.metadata.get(Metadata.CONTENT_TYPE); - } - - public String getContenEncoding() - { - return this.metadata.get(Metadata.CONTENT_ENCODING); - } - - public String getFrom() - { - return this.metadata.get(Metadata.MESSAGE_FROM); - } - - public String getTo() - { - return this.metadata.get(Metadata.MESSAGE_TO); - } - - public String getCC() - { - return this.metadata.get(Metadata.MESSAGE_CC); - } - - public String getBCC() - { - return this.metadata.get(Metadata.MESSAGE_BCC); - } - - public String getRecipientAddress() - { - return this.metadata.get(Metadata.MESSAGE_RECIPIENT_ADDRESS); - } - - public String getMboxSupportedMediaType() - { - return MediaType.application("mbox").getType(); - } -} +package org.sleuthkit.autopsy.thunderbirdparser; + +import java.io.*; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.tika.Tika; +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MimeTypes; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.ParseContext; +import org.apache.tika.sax.BodyContentHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +public class ThunderbirdEmailParser { + + + private InputStream stream; + //Tika object + private Tika tika; + private ThunderbirdMetadata metadata; + private ContentHandler contentHandler; + private String mimeType; + private ThunderbirdMboxParser parser; + private ParseContext context; + + private static ArrayList tikaMimeTypes; + + static + { + tikaMimeTypes = new ArrayList(); + tikaMimeTypes.add(MimeTypes.OCTET_STREAM); + tikaMimeTypes.add(MimeTypes.PLAIN_TEXT); + tikaMimeTypes.add(MimeTypes.XML); + } + + public ThunderbirdEmailParser() + { + this.tika = new Tika(); + } + + public ThunderbirdEmailParser(InputStream inStream) + { + this.tika = new Tika(); + this.stream = inStream; + } + + public ThunderbirdEmailParser(String filepath) + { + this.tika = new Tika(); + this.stream = this.getClass().getResourceAsStream(filepath); + } + + private void init() throws IOException + { + this.tika.setMaxStringLength(10*1024*1024); + this.metadata = new ThunderbirdMetadata(); + //Set MIME Type + //this.mimeType = tika.detect(this.stream); + this.parser = new ThunderbirdMboxParser(); + this.context = new ParseContext(); + this.contentHandler = new BodyContentHandler(10*1024*1024); + } + + public void parse() throws FileNotFoundException, IOException, SAXException, TikaException + { + init(); + parser.parse(this.stream,this.contentHandler, this.metadata, context); + } + + public void parse(InputStream inStream) throws FileNotFoundException, IOException, SAXException, TikaException + { + init(); + parser.parse(inStream,this.contentHandler, this.metadata, context); + } + + public ThunderbirdMetadata getMetadata() + { + return this.metadata; + } + + + //Returns message content, i.e. plain text or html + public String getContent() + { + return this.contentHandler.toString(); + } + + public String detectEmailFileFormat(String filepath) throws IOException + { + return this.tika.detect(filepath); + } + + //Detects the mime type from the first few bytes of the document + public String detectMediaTypeFromBytes(byte[] firstFewBytes, String inDocName) + { + return this.tika.detect(firstFewBytes, inDocName); + } + + + public boolean isValidMimeTypeMbox(byte[] buffer) + { + return (new String(buffer)).startsWith("From "); + } + + //This assumes the file/stream was parsed since we are looking at the metadata + public boolean isValidMboxType() + { + return this.metadata.get(Metadata.CONTENT_TYPE).equals("application/mbox"); + } + + //Get email subject + public String getSubject() + { + return this.metadata.get(Metadata.SUBJECT); + } + + public String getTitle() + { + return this.metadata.get(Metadata.TITLE); + } + + public Long getDateCreated() + { + Long epochtime; + Long ftime = 0L; + + try { + String datetime = this.metadata.get(Metadata.DATE); + epochtime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'").parse(datetime).getTime(); + ftime = epochtime.longValue(); + ftime = ftime / 1000; + } catch (ParseException ex) { + Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); + } + + return ftime; + } + + public String getContenType() + { + return this.metadata.get(Metadata.CONTENT_TYPE); + } + + public String getContenEncoding() + { + return this.metadata.get(Metadata.CONTENT_ENCODING); + } + + public String getFrom() + { + return this.metadata.get(Metadata.AUTHOR); + } + + public String getTo() + { + return this.metadata.get(Metadata.MESSAGE_TO); + } + + public String getCC() + { + return this.metadata.get(Metadata.MESSAGE_CC); + } + + public String getBCC() + { + return this.metadata.get(Metadata.MESSAGE_BCC); + } + + public String getRecipientAddress() + { + return this.metadata.get(Metadata.MESSAGE_RECIPIENT_ADDRESS); + } + + public String getMboxSupportedMediaType() + { + return MediaType.application("mbox").getType(); + } +} diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestService.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestService.java similarity index 96% rename from ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestService.java rename to thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestService.java index b02d899870..a61a34e6e0 100644 --- a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestService.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxFileIngestService.java @@ -1,193 +1,193 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2011 Basis Technology Corp. - * Contact: carrier sleuthkit 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.FileNotFoundException; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.logging.Level; -import java.util.logging.Logger; -import org.apache.tika.exception.TikaException; -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.BlackboardArtifact.ARTIFACT_TYPE; -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; - -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 = "Mbox Parser"; - - 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; - - try { - byte[] t = new byte[(int) 128]; - int byteRead = fsContent.read(t, 0, 128); - isMbox = mbox.isValidMimeTypeMbox(t); - } catch (TskException ex) { - Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } - - - if (isMbox) { - managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName())); - try { - ReadContentInputStream contentStream = new ReadContentInputStream(fsContent); - mbox.parse(contentStream); - String content = mbox.getContent(); - String from = mbox.getFrom(); - String to = mbox.getTo(); - Long date = mbox.getDateCreated(); - String subject = mbox.getSubject(); - String cc = mbox.getCC(); - String bcc = mbox.getBCC(); - Collection bbattributes = new ArrayList(); - 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)); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID(), classname, "", content)); - //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), classname, "",)); - //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)); - 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.SEVERE, null, ex); - } - - - - IngestManager.fireServiceDataEvent(new ServiceDataEvent(classname, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG)); - } catch (FileNotFoundException ex) { - Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } catch (IOException ex) { - Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } catch (SAXException ex) { - Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); - } catch (TikaException ex) { - Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, 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 "Mbox 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() { - } +/* + * Autopsy Forensic Browser + * + * Copyright 2011 Basis Technology Corp. + * Contact: carrier sleuthkit 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.FileNotFoundException; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.logging.Level; +import java.util.logging.Logger; +import org.apache.tika.exception.TikaException; +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.BlackboardArtifact.ARTIFACT_TYPE; +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; + +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"; + + 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; + + try { + byte[] t = new byte[(int) 128]; + int byteRead = fsContent.read(t, 0, 128); + isMbox = mbox.isValidMimeTypeMbox(t); + } catch (TskException ex) { + Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); + } + + + if (isMbox) { + managerProxy.postMessage(IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Processing " + fsContent.getName())); + try { + ReadContentInputStream contentStream = new ReadContentInputStream(fsContent); + mbox.parse(contentStream); + String content = mbox.getContent(); + String from = mbox.getFrom(); + String to = mbox.getTo(); + Long date = mbox.getDateCreated(); + String subject = mbox.getSubject(); + String cc = mbox.getCC(); + String bcc = mbox.getBCC(); + Collection bbattributes = new ArrayList(); + 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)); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_EMAIL_CONTENT_HTML.getTypeID(), classname, "", content)); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_MSG_ID.getTypeID(), classname, "",)); + //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)); + 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.SEVERE, null, ex); + } + + + + IngestManager.fireServiceDataEvent(new ServiceDataEvent(classname, BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG)); + } catch (FileNotFoundException ex) { + Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); + } catch (IOException ex) { + Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); + } catch (SAXException ex) { + Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, null, ex); + } catch (TikaException ex) { + Logger.getLogger(ThunderbirdMboxFileIngestService.class.getName()).log(Level.SEVERE, 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 "Mbox 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() { + } } \ No newline at end of file diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxParser.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxParser.java similarity index 97% rename from ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxParser.java rename to thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxParser.java index 1e8ae0db86..92be98a590 100644 --- a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxParser.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMboxParser.java @@ -1,253 +1,253 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.thunderbirdparser; - -import java.io.*; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Date; -import java.util.Locale; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import org.apache.tika.exception.TikaException; -import org.apache.tika.metadata.Metadata; -import org.apache.tika.mime.MediaType; -import org.apache.tika.parser.AbstractParser; -import org.apache.tika.parser.ParseContext; -import org.xml.sax.ContentHandler; -import org.xml.sax.SAXException; - -/** - * - * @author arivera - */ -public class ThunderbirdMboxParser { - - /** Serial version UID */ - private static final long serialVersionUID = -1762689436731160661L; - - private static final Set SUPPORTED_TYPES = - Collections.singleton(MediaType.application("mbox")); - - public static final String MBOX_MIME_TYPE = "application/mbox"; - public static final String MBOX_RECORD_DIVIDER = "From "; - private static final Pattern EMAIL_HEADER_PATTERN = Pattern.compile("([^ ]+):[ \t]*(.*)"); - private static final Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile("<(.*@.*)>"); - - private static final String EMAIL_HEADER_METADATA_PREFIX = "MboxParser-"; - private static final String EMAIL_FROMLINE_METADATA = EMAIL_HEADER_METADATA_PREFIX + "from"; - - private ThunderbirdXHTMLContentHandler xhtml = null; - - private enum ParseStates { - START, IN_HEADER, IN_CONTENT - } - - public Set getSupportedTypes(ParseContext context) { - return SUPPORTED_TYPES; - } - - public void parse( - InputStream stream, ContentHandler handler, - ThunderbirdMetadata metadata, ParseContext context) - throws IOException, TikaException, SAXException { - - InputStreamReader isr; - try { - // Headers are going to be 7-bit ascii - isr = new InputStreamReader(stream, "US-ASCII"); - } catch (UnsupportedEncodingException e) { - throw new TikaException("US-ASCII is not supported!", e); - } - - BufferedReader reader = new BufferedReader(isr); - - metadata.set(Metadata.CONTENT_TYPE, MBOX_MIME_TYPE); - metadata.set(Metadata.CONTENT_ENCODING, "us-ascii"); - - xhtml = new ThunderbirdXHTMLContentHandler(handler, metadata); - xhtml.startDocument(); - - ThunderbirdMboxParser.ParseStates parseState = ThunderbirdMboxParser.ParseStates.START; - String multiLine = null; - boolean inQuote = false; - int numEmails = 0; - - - // We're going to scan, line-by-line, for a line that starts with - // "From " - - for (String curLine = reader.readLine(); curLine != null; curLine = reader.readLine()) - { - - boolean newMessage = curLine.startsWith(MBOX_RECORD_DIVIDER); - if (newMessage) { - numEmails += 1; - } - - switch (parseState) { - case START: - if (newMessage) { - parseState = ThunderbirdMboxParser.ParseStates.IN_HEADER; - newMessage = false; - // Fall through to IN_HEADER - } else { - break; - } - - case IN_HEADER: - if (newMessage) { - saveHeaderInMetadata(numEmails, metadata, multiLine); - //saveHeaderInMetadata(numEmails, metadata, curLine); - multiLine = curLine; - } - //I think this is never going to be true - else if (curLine.length() == 0) - { - // Blank line is signal that we're transitioning to the content. - - saveHeaderInMetadata(numEmails, metadata, multiLine); - parseState = ThunderbirdMboxParser.ParseStates.IN_CONTENT; - - // Mimic what PackageParser does between entries. - xhtml.startElement("div", "class", "email-entry"); - xhtml.startElement("p"); - inQuote = false; - } - else if ((curLine.startsWith(" ") || curLine.startsWith("\t")) ) - { - multiLine += " " + curLine.trim(); - } - else - { - saveHeaderInMetadata(numEmails, metadata, multiLine); - multiLine = curLine; - } - - break; - - // TODO - use real email parsing support so we can correctly handle - // things like multipart messages and quoted-printable encoding. - // We'd also want this for charset handling, where content isn't 7-bit - // ascii. - case IN_CONTENT: - if (newMessage) { - endMessage(inQuote); - parseState = ThunderbirdMboxParser.ParseStates.IN_HEADER; - multiLine = curLine; - } else { - boolean quoted = curLine.startsWith(">"); - if (inQuote) { - if (!quoted) { - xhtml.endElement("q"); - inQuote = false; - } - } else if (quoted) { - xhtml.startElement("q"); - inQuote = true; - } - - xhtml.characters(curLine); - - // For plain text email, each line is a real break position. - xhtml.element("br", ""); - } - } - } - - if (parseState == ThunderbirdMboxParser.ParseStates.IN_HEADER) { - saveHeaderInMetadata(numEmails, metadata, multiLine); - } else if (parseState == ThunderbirdMboxParser.ParseStates.IN_CONTENT) { - endMessage(inQuote); - } - - xhtml.endDocument(); - } - - private void endMessage(boolean inQuote) throws SAXException { - if (inQuote) { - xhtml.endElement("q"); - } - - xhtml.endElement("p"); - xhtml.endElement("div"); - } - - private void saveHeaderInMetadata(int numEmails, ThunderbirdMetadata metadata, String curLine) - { - - //if ((curLine != null) && curLine.startsWith(MBOX_RECORD_DIVIDER) && (numEmails >= 1)) n - //At this point, the current line we are feeding should never be null!!! - if ((curLine != null) && curLine.startsWith(MBOX_RECORD_DIVIDER)) - { - metadata.add(EMAIL_FROMLINE_METADATA, curLine.substring(MBOX_RECORD_DIVIDER.length())); - return; - } - else if ((curLine == null)) { - return; - } - - Matcher headerMatcher = EMAIL_HEADER_PATTERN.matcher(curLine); - if (!headerMatcher.matches()) { - return; // ignore malformed header lines - } - - String headerTag = headerMatcher.group(1).toLowerCase(); - String headerContent = headerMatcher.group(2); - - if (headerTag.equalsIgnoreCase("From")) { - metadata.add(ThunderbirdMetadata.AUTHOR, headerContent); - metadata.add(ThunderbirdMetadata.CREATOR, headerContent); - } else if (headerTag.equalsIgnoreCase("To") || - headerTag.equalsIgnoreCase("Cc") || - headerTag.equalsIgnoreCase("Bcc")) { - Matcher address = EMAIL_ADDRESS_PATTERN.matcher(headerContent); - if(address.find()) { - metadata.add(ThunderbirdMetadata.MESSAGE_RECIPIENT_ADDRESS, address.group(1)); - } else if(headerContent.indexOf('@') > -1) { - metadata.add(ThunderbirdMetadata.MESSAGE_RECIPIENT_ADDRESS, headerContent); - } - - String property = ThunderbirdMetadata.MESSAGE_TO; - if (headerTag.equalsIgnoreCase("Cc")) { - property = ThunderbirdMetadata.MESSAGE_CC; - } else if (headerTag.equalsIgnoreCase("Bcc")) { - property = ThunderbirdMetadata.MESSAGE_BCC; - } - metadata.add(property, headerContent); - } else if (headerTag.equalsIgnoreCase("Subject")) { - metadata.add(ThunderbirdMetadata.SUBJECT, headerContent); - metadata.add(ThunderbirdMetadata.TITLE, headerContent); - } else if (headerTag.equalsIgnoreCase("Date")) { - try { - Date date = parseDate(headerContent); - metadata.set(ThunderbirdMetadata.DATE, date); - metadata.set(ThunderbirdMetadata.CREATION_DATE, date); - } catch (ParseException e) { - // ignoring date because format was not understood - } - } else if (headerTag.equalsIgnoreCase("Message-Id")) { - metadata.add(ThunderbirdMetadata.IDENTIFIER, headerContent); - } else if (headerTag.equalsIgnoreCase("In-Reply-To")) { - metadata.add(ThunderbirdMetadata.RELATION, headerContent); - } else if (headerTag.equalsIgnoreCase("Content-Type")) { - // TODO - key off content-type in headers to - // set mapping to use for content and convert if necessary. - - metadata.add(ThunderbirdMetadata.CONTENT_TYPE, headerContent); - metadata.add(ThunderbirdMetadata.FORMAT, headerContent); - } else { - metadata.add(EMAIL_HEADER_METADATA_PREFIX + headerTag, headerContent); - } - } - - public static Date parseDate(String headerContent) throws ParseException { - SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); - return dateFormat.parse(headerContent); - } - -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.thunderbirdparser; + +import java.io.*; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Collections; +import java.util.Date; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.tika.exception.TikaException; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.mime.MediaType; +import org.apache.tika.parser.AbstractParser; +import org.apache.tika.parser.ParseContext; +import org.xml.sax.ContentHandler; +import org.xml.sax.SAXException; + +/** + * + * @author arivera + */ +public class ThunderbirdMboxParser { + + /** Serial version UID */ + private static final long serialVersionUID = -1762689436731160661L; + + private static final Set SUPPORTED_TYPES = + Collections.singleton(MediaType.application("mbox")); + + public static final String MBOX_MIME_TYPE = "application/mbox"; + public static final String MBOX_RECORD_DIVIDER = "From "; + private static final Pattern EMAIL_HEADER_PATTERN = Pattern.compile("([^ ]+):[ \t]*(.*)"); + private static final Pattern EMAIL_ADDRESS_PATTERN = Pattern.compile("<(.*@.*)>"); + + private static final String EMAIL_HEADER_METADATA_PREFIX = "MboxParser-"; + private static final String EMAIL_FROMLINE_METADATA = EMAIL_HEADER_METADATA_PREFIX + "from"; + + private ThunderbirdXHTMLContentHandler xhtml = null; + + private enum ParseStates { + START, IN_HEADER, IN_CONTENT + } + + public Set getSupportedTypes(ParseContext context) { + return SUPPORTED_TYPES; + } + + public void parse( + InputStream stream, ContentHandler handler, + ThunderbirdMetadata metadata, ParseContext context) + throws IOException, TikaException, SAXException { + + InputStreamReader isr; + try { + // Headers are going to be 7-bit ascii + isr = new InputStreamReader(stream, "US-ASCII"); + } catch (UnsupportedEncodingException e) { + throw new TikaException("US-ASCII is not supported!", e); + } + + BufferedReader reader = new BufferedReader(isr); + + metadata.set(Metadata.CONTENT_TYPE, MBOX_MIME_TYPE); + metadata.set(Metadata.CONTENT_ENCODING, "us-ascii"); + + xhtml = new ThunderbirdXHTMLContentHandler(handler, metadata); + xhtml.startDocument(); + + ThunderbirdMboxParser.ParseStates parseState = ThunderbirdMboxParser.ParseStates.START; + String multiLine = null; + boolean inQuote = false; + int numEmails = 0; + + + // We're going to scan, line-by-line, for a line that starts with + // "From " + + for (String curLine = reader.readLine(); curLine != null; curLine = reader.readLine()) + { + + boolean newMessage = curLine.startsWith(MBOX_RECORD_DIVIDER); + if (newMessage) { + numEmails += 1; + } + + switch (parseState) { + case START: + if (newMessage) { + parseState = ThunderbirdMboxParser.ParseStates.IN_HEADER; + newMessage = false; + // Fall through to IN_HEADER + } else { + break; + } + + case IN_HEADER: + if (newMessage) { + saveHeaderInMetadata(numEmails, metadata, multiLine); + //saveHeaderInMetadata(numEmails, metadata, curLine); + multiLine = curLine; + } + //I think this is never going to be true + else if (curLine.length() == 0) + { + // Blank line is signal that we're transitioning to the content. + + saveHeaderInMetadata(numEmails, metadata, multiLine); + parseState = ThunderbirdMboxParser.ParseStates.IN_CONTENT; + + // Mimic what PackageParser does between entries. + xhtml.startElement("div", "class", "email-entry"); + xhtml.startElement("p"); + inQuote = false; + } + else if ((curLine.startsWith(" ") || curLine.startsWith("\t")) ) + { + multiLine += " " + curLine.trim(); + } + else + { + saveHeaderInMetadata(numEmails, metadata, multiLine); + multiLine = curLine; + } + + break; + + // TODO - use real email parsing support so we can correctly handle + // things like multipart messages and quoted-printable encoding. + // We'd also want this for charset handling, where content isn't 7-bit + // ascii. + case IN_CONTENT: + if (newMessage) { + endMessage(inQuote); + parseState = ThunderbirdMboxParser.ParseStates.IN_HEADER; + multiLine = curLine; + } else { + boolean quoted = curLine.startsWith(">"); + if (inQuote) { + if (!quoted) { + xhtml.endElement("q"); + inQuote = false; + } + } else if (quoted) { + xhtml.startElement("q"); + inQuote = true; + } + + xhtml.characters(curLine); + + // For plain text email, each line is a real break position. + xhtml.element("br", ""); + } + } + } + + if (parseState == ThunderbirdMboxParser.ParseStates.IN_HEADER) { + saveHeaderInMetadata(numEmails, metadata, multiLine); + } else if (parseState == ThunderbirdMboxParser.ParseStates.IN_CONTENT) { + endMessage(inQuote); + } + + xhtml.endDocument(); + } + + private void endMessage(boolean inQuote) throws SAXException { + if (inQuote) { + xhtml.endElement("q"); + } + + xhtml.endElement("p"); + xhtml.endElement("div"); + } + + private void saveHeaderInMetadata(int numEmails, ThunderbirdMetadata metadata, String curLine) + { + + //if ((curLine != null) && curLine.startsWith(MBOX_RECORD_DIVIDER) && (numEmails >= 1)) n + //At this point, the current line we are feeding should never be null!!! + if ((curLine != null) && curLine.startsWith(MBOX_RECORD_DIVIDER)) + { + metadata.add(EMAIL_FROMLINE_METADATA, curLine.substring(MBOX_RECORD_DIVIDER.length())); + return; + } + else if ((curLine == null)) { + return; + } + + Matcher headerMatcher = EMAIL_HEADER_PATTERN.matcher(curLine); + if (!headerMatcher.matches()) { + return; // ignore malformed header lines + } + + String headerTag = headerMatcher.group(1).toLowerCase(); + String headerContent = headerMatcher.group(2); + + if (headerTag.equalsIgnoreCase("From")) { + metadata.add(ThunderbirdMetadata.AUTHOR, headerContent); + metadata.add(ThunderbirdMetadata.CREATOR, headerContent); + } else if (headerTag.equalsIgnoreCase("To") || + headerTag.equalsIgnoreCase("Cc") || + headerTag.equalsIgnoreCase("Bcc")) { + Matcher address = EMAIL_ADDRESS_PATTERN.matcher(headerContent); + if(address.find()) { + metadata.add(ThunderbirdMetadata.MESSAGE_RECIPIENT_ADDRESS, address.group(1)); + } else if(headerContent.indexOf('@') > -1) { + metadata.add(ThunderbirdMetadata.MESSAGE_RECIPIENT_ADDRESS, headerContent); + } + + String property = ThunderbirdMetadata.MESSAGE_TO; + if (headerTag.equalsIgnoreCase("Cc")) { + property = ThunderbirdMetadata.MESSAGE_CC; + } else if (headerTag.equalsIgnoreCase("Bcc")) { + property = ThunderbirdMetadata.MESSAGE_BCC; + } + metadata.add(property, headerContent); + } else if (headerTag.equalsIgnoreCase("Subject")) { + metadata.add(ThunderbirdMetadata.SUBJECT, headerContent); + metadata.add(ThunderbirdMetadata.TITLE, headerContent); + } else if (headerTag.equalsIgnoreCase("Date")) { + try { + Date date = parseDate(headerContent); + metadata.set(ThunderbirdMetadata.DATE, date); + metadata.set(ThunderbirdMetadata.CREATION_DATE, date); + } catch (ParseException e) { + // ignoring date because format was not understood + } + } else if (headerTag.equalsIgnoreCase("Message-Id")) { + metadata.add(ThunderbirdMetadata.IDENTIFIER, headerContent); + } else if (headerTag.equalsIgnoreCase("In-Reply-To")) { + metadata.add(ThunderbirdMetadata.RELATION, headerContent); + } else if (headerTag.equalsIgnoreCase("Content-Type")) { + // TODO - key off content-type in headers to + // set mapping to use for content and convert if necessary. + + metadata.add(ThunderbirdMetadata.CONTENT_TYPE, headerContent); + metadata.add(ThunderbirdMetadata.FORMAT, headerContent); + } else { + metadata.add(EMAIL_HEADER_METADATA_PREFIX + headerTag, headerContent); + } + } + + public static Date parseDate(String headerContent) throws ParseException { + SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); + return dateFormat.parse(headerContent); + } + +} diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMetadata.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMetadata.java similarity index 97% rename from ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMetadata.java rename to thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMetadata.java index e0093dac45..0ecb09215e 100644 --- a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMetadata.java +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdMetadata.java @@ -1,447 +1,447 @@ -/* - * To change this template, choose Tools | Templates - * and open the template in the editor. - */ -package org.sleuthkit.autopsy.thunderbirdparser; - -import java.io.Serializable; -import java.text.DateFormat; -import java.text.DateFormatSymbols; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; -import org.apache.tika.metadata.*; - -/** - * - * @author arivera - */ -public class ThunderbirdMetadata implements CreativeCommons, DublinCore, Geographic, HttpHeaders, - IPTC, Message, MSOffice, ClimateForcast, TIFF, TikaMetadataKeys, TikaMimeKeys, - Serializable { - - private int strArrCount = 0; - - /** Serial version UID */ - private static final long serialVersionUID = 5623926545693153182L; - - /** - * A map of all metadata attributes. - */ - private Map> metadata = null; - - /** - * The UTC time zone. Not sure if {@link TimeZone#getTimeZone(String)} - * understands "UTC" in all environments, but it'll fall back to GMT - * in such cases, which is in practice equivalent to UTC. - */ - private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); - - /** - * Custom time zone used to interpret date values without a time - * component in a way that most likely falls within the same day - * regardless of in which time zone it is later interpreted. For - * example, the "2012-02-17" date would map to "2012-02-17T12:00:00Z" - * (instead of the default "2012-02-17T00:00:00Z"), which would still - * map to "2012-02-17" if interpreted in say Pacific time (while the - * default mapping would result in "2012-02-16" for UTC-8). - */ - private static final TimeZone MIDDAY = TimeZone.getTimeZone("GMT-12:00"); - - /** - * Some parsers will have the date as a ISO-8601 string - * already, and will set that into the Metadata object. - * So we can return Date objects for these, this is the - * list (in preference order) of the various ISO-8601 - * variants that we try when processing a date based - * property. - */ - private static final DateFormat[] iso8601InputFormats = new DateFormat[] { - // yyyy-mm-ddThh... - createDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", UTC), // UTC/Zulu - createDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", null), // With timezone - createDateFormat("yyyy-MM-dd'T'HH:mm:ss", null), // Without timezone - // yyyy-mm-dd hh... - createDateFormat("yyyy-MM-dd' 'HH:mm:ss'Z'", UTC), // UTC/Zulu - createDateFormat("yyyy-MM-dd' 'HH:mm:ssZ", null), // With timezone - createDateFormat("yyyy-MM-dd' 'HH:mm:ss", null), // Without timezone - // Date without time, set to Midday UTC - createDateFormat("yyyy-MM-dd", MIDDAY), // Normal date format - createDateFormat("yyyy:MM:dd", MIDDAY), // Image (IPTC/EXIF) format - }; - - private static DateFormat createDateFormat(String format, TimeZone timezone) { - SimpleDateFormat sdf = - new SimpleDateFormat(format, new DateFormatSymbols(Locale.US)); - if (timezone != null) { - sdf.setTimeZone(timezone); - } - return sdf; - } - - /** - * Parses the given date string. This method is synchronized to prevent - * concurrent access to the thread-unsafe date formats. - * - * @see TIKA-495 - * @param date date string - * @return parsed date, or null if the date can't be parsed - */ - private static synchronized Date parseDate(String date) { - // Java doesn't like timezones in the form ss+hh:mm - // It only likes the hhmm form, without the colon - int n = date.length(); - if (date.charAt(n - 3) == ':' - && (date.charAt(n - 6) == '+' || date.charAt(n - 6) == '-')) { - date = date.substring(0, n - 3) + date.substring(n - 2); - } - - // Try several different ISO-8601 variants - for (DateFormat format : iso8601InputFormats) { - try { - return format.parse(date); - } catch (ParseException ignore) { - } - } - return null; - } - - /** - * Returns a ISO 8601 representation of the given date. This method is - * synchronized to prevent concurrent access to the thread-unsafe date - * formats. - * - * @see TIKA-495 - * @param date given date - * @return ISO 8601 date string - */ - private static String formatDate(Date date) { - Calendar calendar = GregorianCalendar.getInstance(UTC, Locale.US); - calendar.setTime(date); - return String.format( - "%04d-%02d-%02dT%02d:%02d:%02dZ", - calendar.get(Calendar.YEAR), - calendar.get(Calendar.MONTH) + 1, - calendar.get(Calendar.DAY_OF_MONTH), - calendar.get(Calendar.HOUR_OF_DAY), - calendar.get(Calendar.MINUTE), - calendar.get(Calendar.SECOND)); - } - - /** - * Constructs a new, empty metadata. - */ - public ThunderbirdMetadata() { - metadata = new HashMap>(); - } - - /** - * Returns true if named value is multivalued. - * - * @param name - * name of metadata - * @return true is named value is multivalued, false if single value or null - */ - public boolean isMultiValued(final String name) { - return metadata.get(name) != null && metadata.get(name).size() > 1; - } - - /** - * Returns an array of the names contained in the metadata. - * - * @return Metadata names - */ - public ArrayList names() { - return new ArrayList(metadata.keySet());//.toArray(new String[metadata.keySet().size()]); - } - - /** - * Get the value associated to a metadata name. If many values are assiociated - * to the specified name, then the first one is returned. - * - * @param name - * of the metadata. - * @return the value associated to the specified metadata name. - */ - public String get(final String name) { - ArrayList values = metadata.get(name); - if (values == null) { - return null; - } else { - return values.get(0); - } - } - - /** - * Returns the value (if any) of the identified metadata property. - * - * @since Apache Tika 0.7 - * @param property property definition - * @return property value, or null if the property is not set - */ - public String get(Property property) { - return get(property.getName()); - } - - /** - * Returns the value of the identified Integer based metadata property. - * - * @since Apache Tika 0.8 - * @param property simple integer property definition - * @return property value as a Integer, or null if the property is not set, or not a valid Integer - */ - public Integer getInt(Property property) { - if(property.getPropertyType() != Property.PropertyType.SIMPLE) { - return null; - } - if(property.getValueType() != Property.ValueType.INTEGER) { - return null; - } - - String v = get(property); - if(v == null) { - return null; - } - try { - return Integer.valueOf(v); - } catch(NumberFormatException e) { - return null; - } - } - - /** - * Returns the value of the identified Date based metadata property. - * - * @since Apache Tika 0.8 - * @param property simple date property definition - * @return property value as a Date, or null if the property is not set, or not a valid Date - */ - public Date getDate(Property property) { - if(property.getPropertyType() != Property.PropertyType.SIMPLE) { - return null; - } - if(property.getValueType() != Property.ValueType.DATE) { - return null; - } - - String v = get(property); - if (v != null) { - return parseDate(v); - } else { - return null; - } - } - - /** - * Get the values associated to a metadata name. - * - * @param name - * of the metadata. - * @return the values associated to a metadata name. - */ - public ArrayList getValues(final String name) { - return _getValues(name); - } - - private ArrayList _getValues(final String name) { - ArrayList values = metadata.get(name); - if (values == null) { - values = new ArrayList(); - } - return values; - } - - /** - * Add a metadata name/value mapping. Add the specified value to the list of - * values associated to the specified metadata name. - * - * @param name - * the metadata name. - * @param value - * the metadata value. - */ - public void add(final String name, final String value) { - ArrayList values = metadata.get(name); - if (values == null) { - set(name, value); - } else { - //ArrayList newValues = new ArrayList();//new String[values.size() + 1]; - //System.arraycopy(values, 0, newValues, 0, values.size()); - //newValues[newValues.length - 1] = value; - values.add(value); - metadata.put(name, values); - } - } - - /** - * Copy All key-value pairs from properties. - * - * @param properties - * properties to copy from - */ - @SuppressWarnings("unchecked") - public void setAll(Properties properties) { - ArrayList propArr = new ArrayList(); - Enumeration names = - (Enumeration) properties.propertyNames(); - while (names.hasMoreElements()) { - String name = names.nextElement(); - propArr.add(properties.getProperty(name) ); - metadata.put(name, propArr); - } - } - - /** - * Set metadata name/value. Associate the specified value to the specified - * metadata name. If some previous values were associated to this name, they - * are removed. - * - * @param name - * the metadata name. - * @param value - * the metadata value. - */ - public void set(String name, String value) { - ArrayList strArr = this.metadata.get(name); - - if(strArr != null) - { - metadata.put(name, strArr); - } - else - { - strArr = new ArrayList(); - strArr.add(value); - metadata.put(name,strArr); - } - ++strArrCount; - } - - /** - * Sets the value of the identified metadata property. - * - * @since Apache Tika 0.7 - * @param property property definition - * @param value property value - */ - public void set(Property property, String value) { - set(property.getName(), value); - } - - /** - * Sets the integer value of the identified metadata property. - * - * @since Apache Tika 0.8 - * @param property simple integer property definition - * @param value property value - */ - public void set(Property property, int value) { - if(property.getPropertyType() != Property.PropertyType.SIMPLE) { - throw new PropertyTypeException(Property.PropertyType.SIMPLE, property.getPropertyType()); - } - if(property.getValueType() != Property.ValueType.INTEGER) { - throw new PropertyTypeException(Property.ValueType.INTEGER, property.getValueType()); - } - set(property.getName(), Integer.toString(value)); - } - - /** - * Sets the real or rational value of the identified metadata property. - * - * @since Apache Tika 0.8 - * @param property simple real or simple rational property definition - * @param value property value - */ - public void set(Property property, double value) { - if(property.getPropertyType() != Property.PropertyType.SIMPLE) { - throw new PropertyTypeException(Property.PropertyType.SIMPLE, property.getPropertyType()); - } - if(property.getValueType() != Property.ValueType.REAL && - property.getValueType() != Property.ValueType.RATIONAL) { - throw new PropertyTypeException(Property.ValueType.REAL, property.getValueType()); - } - set(property.getName(), Double.toString(value)); - } - - /** - * Sets the date value of the identified metadata property. - * - * @since Apache Tika 0.8 - * @param property simple integer property definition - * @param date property value - */ - public void set(Property property, Date date) { - if(property.getPropertyType() != Property.PropertyType.SIMPLE) { - throw new PropertyTypeException(Property.PropertyType.SIMPLE, property.getPropertyType()); - } - if(property.getValueType() != Property.ValueType.DATE) { - throw new PropertyTypeException(Property.ValueType.DATE, property.getValueType()); - } - set(property.getName(), formatDate(date)); - } - - /** - * Remove a metadata and all its associated values. - * - * @param name - * metadata name to remove - */ - public void remove(String name) { - metadata.remove(name); - } - - /** - * Returns the number of metadata names in this metadata. - * - * @return number of metadata names - */ - public int size() { - return metadata.size(); - } - - public boolean equals(Object o) { - - if (o == null) { - return false; - } - - ThunderbirdMetadata other = null; - try { - other = (ThunderbirdMetadata) o; - } catch (ClassCastException cce) { - return false; - } - - if (other.size() != size()) { - return false; - } - - ArrayList names = names(); - for (String str : names) - {//int i = 0; i < names.length; i++) { - ArrayList otherValues = other._getValues(str); - ArrayList thisValues = _getValues(str); - if (otherValues.size() != thisValues.size()) { - return false; - } - for (int j = 0; j < otherValues.size(); j++) { - if (!otherValues.get(j).equals(thisValues.get(j))) { - return false; - } - } - } - return true; - } - - public String toString() { - StringBuffer buf = new StringBuffer(); - ArrayList names = names(); - for (int i = 0; i < names.size(); i++) { - ArrayList values = _getValues(names.get(i)); - for (int j = 0; j < values.size(); j++) { - buf.append(names.get(i)).append("=").append(values.get(j)).append(" "); - } - } - return buf.toString(); - } -} +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.thunderbirdparser; + +import java.io.Serializable; +import java.text.DateFormat; +import java.text.DateFormatSymbols; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import org.apache.tika.metadata.*; + +/** + * + * @author arivera + */ +public class ThunderbirdMetadata implements CreativeCommons, DublinCore, Geographic, HttpHeaders, + IPTC, Message, MSOffice, ClimateForcast, TIFF, TikaMetadataKeys, TikaMimeKeys, + Serializable { + + private int strArrCount = 0; + + /** Serial version UID */ + private static final long serialVersionUID = 5623926545693153182L; + + /** + * A map of all metadata attributes. + */ + private Map> metadata = null; + + /** + * The UTC time zone. Not sure if {@link TimeZone#getTimeZone(String)} + * understands "UTC" in all environments, but it'll fall back to GMT + * in such cases, which is in practice equivalent to UTC. + */ + private static final TimeZone UTC = TimeZone.getTimeZone("UTC"); + + /** + * Custom time zone used to interpret date values without a time + * component in a way that most likely falls within the same day + * regardless of in which time zone it is later interpreted. For + * example, the "2012-02-17" date would map to "2012-02-17T12:00:00Z" + * (instead of the default "2012-02-17T00:00:00Z"), which would still + * map to "2012-02-17" if interpreted in say Pacific time (while the + * default mapping would result in "2012-02-16" for UTC-8). + */ + private static final TimeZone MIDDAY = TimeZone.getTimeZone("GMT-12:00"); + + /** + * Some parsers will have the date as a ISO-8601 string + * already, and will set that into the Metadata object. + * So we can return Date objects for these, this is the + * list (in preference order) of the various ISO-8601 + * variants that we try when processing a date based + * property. + */ + private static final DateFormat[] iso8601InputFormats = new DateFormat[] { + // yyyy-mm-ddThh... + createDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", UTC), // UTC/Zulu + createDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", null), // With timezone + createDateFormat("yyyy-MM-dd'T'HH:mm:ss", null), // Without timezone + // yyyy-mm-dd hh... + createDateFormat("yyyy-MM-dd' 'HH:mm:ss'Z'", UTC), // UTC/Zulu + createDateFormat("yyyy-MM-dd' 'HH:mm:ssZ", null), // With timezone + createDateFormat("yyyy-MM-dd' 'HH:mm:ss", null), // Without timezone + // Date without time, set to Midday UTC + createDateFormat("yyyy-MM-dd", MIDDAY), // Normal date format + createDateFormat("yyyy:MM:dd", MIDDAY), // Image (IPTC/EXIF) format + }; + + private static DateFormat createDateFormat(String format, TimeZone timezone) { + SimpleDateFormat sdf = + new SimpleDateFormat(format, new DateFormatSymbols(Locale.US)); + if (timezone != null) { + sdf.setTimeZone(timezone); + } + return sdf; + } + + /** + * Parses the given date string. This method is synchronized to prevent + * concurrent access to the thread-unsafe date formats. + * + * @see TIKA-495 + * @param date date string + * @return parsed date, or null if the date can't be parsed + */ + private static synchronized Date parseDate(String date) { + // Java doesn't like timezones in the form ss+hh:mm + // It only likes the hhmm form, without the colon + int n = date.length(); + if (date.charAt(n - 3) == ':' + && (date.charAt(n - 6) == '+' || date.charAt(n - 6) == '-')) { + date = date.substring(0, n - 3) + date.substring(n - 2); + } + + // Try several different ISO-8601 variants + for (DateFormat format : iso8601InputFormats) { + try { + return format.parse(date); + } catch (ParseException ignore) { + } + } + return null; + } + + /** + * Returns a ISO 8601 representation of the given date. This method is + * synchronized to prevent concurrent access to the thread-unsafe date + * formats. + * + * @see TIKA-495 + * @param date given date + * @return ISO 8601 date string + */ + private static String formatDate(Date date) { + Calendar calendar = GregorianCalendar.getInstance(UTC, Locale.US); + calendar.setTime(date); + return String.format( + "%04d-%02d-%02dT%02d:%02d:%02dZ", + calendar.get(Calendar.YEAR), + calendar.get(Calendar.MONTH) + 1, + calendar.get(Calendar.DAY_OF_MONTH), + calendar.get(Calendar.HOUR_OF_DAY), + calendar.get(Calendar.MINUTE), + calendar.get(Calendar.SECOND)); + } + + /** + * Constructs a new, empty metadata. + */ + public ThunderbirdMetadata() { + metadata = new HashMap>(); + } + + /** + * Returns true if named value is multivalued. + * + * @param name + * name of metadata + * @return true is named value is multivalued, false if single value or null + */ + public boolean isMultiValued(final String name) { + return metadata.get(name) != null && metadata.get(name).size() > 1; + } + + /** + * Returns an array of the names contained in the metadata. + * + * @return Metadata names + */ + public ArrayList names() { + return new ArrayList(metadata.keySet());//.toArray(new String[metadata.keySet().size()]); + } + + /** + * Get the value associated to a metadata name. If many values are assiociated + * to the specified name, then the first one is returned. + * + * @param name + * of the metadata. + * @return the value associated to the specified metadata name. + */ + public String get(final String name) { + ArrayList values = metadata.get(name); + if (values == null) { + return null; + } else { + return values.get(0); + } + } + + /** + * Returns the value (if any) of the identified metadata property. + * + * @since Apache Tika 0.7 + * @param property property definition + * @return property value, or null if the property is not set + */ + public String get(Property property) { + return get(property.getName()); + } + + /** + * Returns the value of the identified Integer based metadata property. + * + * @since Apache Tika 0.8 + * @param property simple integer property definition + * @return property value as a Integer, or null if the property is not set, or not a valid Integer + */ + public Integer getInt(Property property) { + if(property.getPropertyType() != Property.PropertyType.SIMPLE) { + return null; + } + if(property.getValueType() != Property.ValueType.INTEGER) { + return null; + } + + String v = get(property); + if(v == null) { + return null; + } + try { + return Integer.valueOf(v); + } catch(NumberFormatException e) { + return null; + } + } + + /** + * Returns the value of the identified Date based metadata property. + * + * @since Apache Tika 0.8 + * @param property simple date property definition + * @return property value as a Date, or null if the property is not set, or not a valid Date + */ + public Date getDate(Property property) { + if(property.getPropertyType() != Property.PropertyType.SIMPLE) { + return null; + } + if(property.getValueType() != Property.ValueType.DATE) { + return null; + } + + String v = get(property); + if (v != null) { + return parseDate(v); + } else { + return null; + } + } + + /** + * Get the values associated to a metadata name. + * + * @param name + * of the metadata. + * @return the values associated to a metadata name. + */ + public ArrayList getValues(final String name) { + return _getValues(name); + } + + private ArrayList _getValues(final String name) { + ArrayList values = metadata.get(name); + if (values == null) { + values = new ArrayList(); + } + return values; + } + + /** + * Add a metadata name/value mapping. Add the specified value to the list of + * values associated to the specified metadata name. + * + * @param name + * the metadata name. + * @param value + * the metadata value. + */ + public void add(final String name, final String value) { + ArrayList values = metadata.get(name); + if (values == null) { + set(name, value); + } else { + //ArrayList newValues = new ArrayList();//new String[values.size() + 1]; + //System.arraycopy(values, 0, newValues, 0, values.size()); + //newValues[newValues.length - 1] = value; + values.add(value); + metadata.put(name, values); + } + } + + /** + * Copy All key-value pairs from properties. + * + * @param properties + * properties to copy from + */ + @SuppressWarnings("unchecked") + public void setAll(Properties properties) { + ArrayList propArr = new ArrayList(); + Enumeration names = + (Enumeration) properties.propertyNames(); + while (names.hasMoreElements()) { + String name = names.nextElement(); + propArr.add(properties.getProperty(name) ); + metadata.put(name, propArr); + } + } + + /** + * Set metadata name/value. Associate the specified value to the specified + * metadata name. If some previous values were associated to this name, they + * are removed. + * + * @param name + * the metadata name. + * @param value + * the metadata value. + */ + public void set(String name, String value) { + ArrayList strArr = this.metadata.get(name); + + if(strArr != null) + { + metadata.put(name, strArr); + } + else + { + strArr = new ArrayList(); + strArr.add(value); + metadata.put(name,strArr); + } + ++strArrCount; + } + + /** + * Sets the value of the identified metadata property. + * + * @since Apache Tika 0.7 + * @param property property definition + * @param value property value + */ + public void set(Property property, String value) { + set(property.getName(), value); + } + + /** + * Sets the integer value of the identified metadata property. + * + * @since Apache Tika 0.8 + * @param property simple integer property definition + * @param value property value + */ + public void set(Property property, int value) { + if(property.getPropertyType() != Property.PropertyType.SIMPLE) { + throw new PropertyTypeException(Property.PropertyType.SIMPLE, property.getPropertyType()); + } + if(property.getValueType() != Property.ValueType.INTEGER) { + throw new PropertyTypeException(Property.ValueType.INTEGER, property.getValueType()); + } + set(property.getName(), Integer.toString(value)); + } + + /** + * Sets the real or rational value of the identified metadata property. + * + * @since Apache Tika 0.8 + * @param property simple real or simple rational property definition + * @param value property value + */ + public void set(Property property, double value) { + if(property.getPropertyType() != Property.PropertyType.SIMPLE) { + throw new PropertyTypeException(Property.PropertyType.SIMPLE, property.getPropertyType()); + } + if(property.getValueType() != Property.ValueType.REAL && + property.getValueType() != Property.ValueType.RATIONAL) { + throw new PropertyTypeException(Property.ValueType.REAL, property.getValueType()); + } + set(property.getName(), Double.toString(value)); + } + + /** + * Sets the date value of the identified metadata property. + * + * @since Apache Tika 0.8 + * @param property simple integer property definition + * @param date property value + */ + public void set(Property property, Date date) { + if(property.getPropertyType() != Property.PropertyType.SIMPLE) { + throw new PropertyTypeException(Property.PropertyType.SIMPLE, property.getPropertyType()); + } + if(property.getValueType() != Property.ValueType.DATE) { + throw new PropertyTypeException(Property.ValueType.DATE, property.getValueType()); + } + set(property.getName(), formatDate(date)); + } + + /** + * Remove a metadata and all its associated values. + * + * @param name + * metadata name to remove + */ + public void remove(String name) { + metadata.remove(name); + } + + /** + * Returns the number of metadata names in this metadata. + * + * @return number of metadata names + */ + public int size() { + return metadata.size(); + } + + public boolean equals(Object o) { + + if (o == null) { + return false; + } + + ThunderbirdMetadata other = null; + try { + other = (ThunderbirdMetadata) o; + } catch (ClassCastException cce) { + return false; + } + + if (other.size() != size()) { + return false; + } + + ArrayList names = names(); + for (String str : names) + {//int i = 0; i < names.length; i++) { + ArrayList otherValues = other._getValues(str); + ArrayList thisValues = _getValues(str); + if (otherValues.size() != thisValues.size()) { + return false; + } + for (int j = 0; j < otherValues.size(); j++) { + if (!otherValues.get(j).equals(thisValues.get(j))) { + return false; + } + } + } + return true; + } + + public String toString() { + StringBuffer buf = new StringBuffer(); + ArrayList names = names(); + for (int i = 0; i < names.size(); i++) { + ArrayList values = _getValues(names.get(i)); + for (int j = 0; j < values.size(); j++) { + buf.append(names.get(i)).append("=").append(values.get(j)).append(" "); + } + } + return buf.toString(); + } +} diff --git a/ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdXHTMLContentHandler.java b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdXHTMLContentHandler.java similarity index 100% rename from ThunderbirdMboxEmailModule/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdXHTMLContentHandler.java rename to thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/ThunderbirdXHTMLContentHandler.java diff --git a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/layer.xml b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/layer.xml similarity index 73% rename from MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/layer.xml rename to thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/layer.xml index ebe57234b4..627a7335ab 100644 --- a/MboxEmailModule/src/org/sleuthkit/autopsy/mboxparser/layer.xml +++ b/thunderbirdparser/src/org/sleuthkit/autopsy/thunderbirdparser/layer.xml @@ -2,9 +2,9 @@ - + - +