This commit is contained in:
jmillman 2013-09-11 09:26:58 -04:00
commit b8a67ae7db
18 changed files with 448 additions and 131 deletions

View File

@ -48,7 +48,7 @@ final class AddImageVisualPanel1 extends JPanel {
static final String encaseDesc = "Encase Images (*.e01)";
static GeneralFilter encaseFilter = new GeneralFilter(encaseExt, encaseDesc);
static final List<String> allExt = new ArrayList<String>();
{
static {
allExt.addAll(rawExt);
allExt.addAll(encaseExt);
}

View File

@ -43,7 +43,6 @@ public class ImageFilePanel extends ContentTypePanel implements DocumentListener
fc.setDragEnabled(false);
fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
fc.setMultiSelectionEnabled(false);
fc.addChoosableFileFilter(AddImageVisualPanel1.allFilter);
fc.addChoosableFileFilter(AddImageVisualPanel1.rawFilter);
fc.addChoosableFileFilter(AddImageVisualPanel1.encaseFilter);
fc.setFileFilter(AddImageVisualPanel1.allFilter);

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8" ?>
<Form version="1.5" maxVersion="1.8" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
<NonVisualComponents>
<Container class="javax.swing.JPopupMenu" name="jPopupMenu1">
<Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
<Property name="useNullLayout" type="boolean" value="true"/>
</Layout>
</Container>
</NonVisualComponents>
<AuxValues>
<AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
<AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
<AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
<AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
<AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
</AuxValues>
<Layout>
<DimensionLayout dim="0">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" alignment="0" pref="400" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
<DimensionLayout dim="1">
<Group type="103" groupAlignment="0" attributes="0">
<Component id="jScrollPane2" alignment="0" pref="300" max="32767" attributes="0"/>
</Group>
</DimensionLayout>
</Layout>
<SubComponents>
<Container class="javax.swing.JScrollPane" name="jScrollPane2">
<AuxValues>
<AuxValue name="autoScrollPane" type="java.lang.Boolean" value="true"/>
</AuxValues>
<Layout class="org.netbeans.modules.form.compat2.layouts.support.JScrollPaneSupportLayout"/>
<SubComponents>
<Component class="javax.swing.JTextPane" name="jTextPane1">
<Properties>
<Property name="editable" type="boolean" value="false"/>
</Properties>
</Component>
</SubComponents>
</Container>
</SubComponents>
</Form>

View File

@ -0,0 +1,189 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.contentviewers;
import java.awt.Component;
import javax.swing.JTextPane;
import org.openide.nodes.Node;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.TskCoreException;
/**
* Shows file metadata as a list to make it easy to copy and paste.
* Typically shows the same data that can also be found in the ResultViewer table,
* just a different order and allows the full path to be visible in the bottom area.
*/
@ServiceProvider(service = DataContentViewer.class, position = 3)
public class Metadata extends javax.swing.JPanel implements DataContentViewer
{
/**
* Creates new form Metadata
*/
public Metadata() {
initComponents();
customizeComponents();
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jPopupMenu1 = new javax.swing.JPopupMenu();
jScrollPane2 = new javax.swing.JScrollPane();
jTextPane1 = new javax.swing.JTextPane();
jTextPane1.setEditable(false);
jScrollPane2.setViewportView(jTextPane1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 400, Short.MAX_VALUE)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 300, Short.MAX_VALUE)
);
}// </editor-fold>//GEN-END:initComponents
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPopupMenu jPopupMenu1;
private javax.swing.JScrollPane jScrollPane2;
private javax.swing.JTextPane jTextPane1;
// End of variables declaration//GEN-END:variables
private void customizeComponents(){
/*
jTextPane1.setComponentPopupMenu(rightClickMenu);
ActionListener actList = new ActionListener(){
@Override
public void actionPerformed(ActionEvent e){
JMenuItem jmi = (JMenuItem) e.getSource();
if(jmi.equals(copyMenuItem))
outputViewPane.copy();
else if(jmi.equals(selectAllMenuItem))
outputViewPane.selectAll();
}
};
copyMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList);
*/
Utilities.configureTextPaneAsHtml(jTextPane1);
}
private void setText(String str) {
jTextPane1.setText("<html><body>" + str + "</body></html>");
}
private void startTable(StringBuilder sb) {
sb.append("<table>");
}
private void endTable(StringBuilder sb) {
sb.append("</table>");
}
private void addRow(StringBuilder sb, String key, String value) {
sb.append("<tr><td>");
sb.append(key);
sb.append("</td><td>");
sb.append(value);
sb.append("</td></tr>");
}
@Override
public void setNode(Node node) {
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
if (file == null) {
setText("Non-file passed in");
return;
}
StringBuilder sb = new StringBuilder();
startTable(sb);
try {
addRow(sb, "Name", file.getUniquePath());
} catch (TskCoreException ex) {
addRow(sb, "Name", file.getParentPath() + "/" + file.getName());
}
addRow(sb, "Modified", file.getMtimeAsDate());
addRow(sb, "Accessed", file.getAtimeAsDate());
addRow(sb, "Created", file.getCrtimeAsDate());
addRow(sb, "Changed", file.getCtimeAsDate());
String md5 = file.getMd5Hash();
if (md5 == null) {
md5 = "Not calculated";
}
addRow(sb, "MD5", md5);
endTable(sb);
setText(sb.toString());
}
@Override
public String getTitle() {
return "Metadata";
}
@Override
public String getToolTip() {
return "";
}
@Override
public DataContentViewer createInstance() {
return new Metadata();
}
@Override
public Component getComponent() {
return this;
}
@Override
public void resetComponent() {
return;
}
@Override
public boolean isSupported(Node node) {
AbstractFile file = node.getLookup().lookup(AbstractFile.class);
if (file == null) {
return false;
}
return true;
}
@Override
public int isPreferred(Node node, boolean isSupported) {
return 1;
}
}

View File

@ -0,0 +1,49 @@
/*
* Autopsy Forensic Browser
*
* Copyright 2013 Basis Technology Corp.
* Contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.sleuthkit.autopsy.contentviewers;
import javax.swing.JTextPane;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
/**
*
* Methods common to ContentViewers.
*/
public class Utilities {
public static void configureTextPaneAsHtml(JTextPane pane) {
pane.setContentType("text/html;charset=UTF-8");
HTMLEditorKit kit = new HTMLEditorKit();
pane.setEditorKit(kit);
StyleSheet styleSheet = kit.getStyleSheet();
/* I tried to play around with inheritence on font-size and it didn't
* always work. Defined all of the basics just in case.
* @@@ IngestInboxViewer also defines styles similar to this. Consider
* a method that sets consistent styles for all viewers and takes font
* size as an argument.
*/
styleSheet.addRule("body {font-family:Arial;font-size:14pt;}");
styleSheet.addRule("p {font-family:Arial;font-size:14pt;}");
styleSheet.addRule("li {font-family:Arial;font-size:14pt;}");
styleSheet.addRule("td {font-family:Arial;font-size:14pt;overflow:hidden;padding-right:5px;padding-left:5px;}");
styleSheet.addRule("th {font-family:Arial;font-size:14pt;overflow:hidden;padding-right:5px;padding-left:5px;font-weight:bold;}");
styleSheet.addRule("p {font-family:Arial;font-size:14pt;}");
}
}

View File

@ -31,11 +31,10 @@ import org.sleuthkit.autopsy.coreutils.Logger;
import javax.swing.JMenuItem;
import javax.swing.JTextPane;
import javax.swing.SwingWorker;
import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.StyleSheet;
import org.openide.nodes.Node;
import org.openide.util.Lookup;
import org.openide.util.lookup.ServiceProvider;
import org.sleuthkit.autopsy.contentviewers.Utilities;
import org.sleuthkit.autopsy.corecomponentinterfaces.DataContentViewer;
import org.sleuthkit.autopsy.datamodel.ArtifactStringContent;
import org.sleuthkit.datamodel.BlackboardArtifact;
@ -245,22 +244,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
copyMenuItem.addActionListener(actList);
selectAllMenuItem.addActionListener(actList);
outputViewPane.setContentType("text/html;charset=UTF-8");
HTMLEditorKit kit = new HTMLEditorKit();
outputViewPane.setEditorKit(kit);
StyleSheet styleSheet = kit.getStyleSheet();
/* I tried to play around with inheritence on font-size and it didn't
* always work. Defined all of the basics just in case.
* @@@ IngestInboxViewer also defines styles similar to this. Consider
* a method that sets consistent styles for all viewers and takes font
* size as an argument.
*/
styleSheet.addRule("body {font-family:Arial;font-size:14pt;}");
styleSheet.addRule("p {font-family:Arial;font-size:14pt;}");
styleSheet.addRule("li {font-family:Arial;font-size:14pt;}");
styleSheet.addRule("td {font-family:Arial;font-size:14pt;overflow:hidden;padding-right:5px;padding-left:5px;}");
styleSheet.addRule("th {font-family:Arial;font-size:14pt;overflow:hidden;padding-right:5px;padding-left:5px;font-weight:bold;}");
styleSheet.addRule("p {font-family:Arial;font-size:14pt;}");
Utilities.configureTextPaneAsHtml(outputViewPane);
}
/**
@ -304,7 +288,7 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
@Override
public String getTitle() {
return "Result View";
return "Results";
}
@Override

View File

@ -390,7 +390,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont
@Override
public String getTitle() {
return "Hex View";
return "Hex";
}
@Override

View File

@ -162,7 +162,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo
@Override
public String getTitle() {
return "Media View";
return "Media";
}
@Override

View File

@ -443,7 +443,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC
@Override
public String getTitle() {
return "String View";
return "Strings";
}
@Override

View File

@ -385,7 +385,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer {
@Override
public String getTitle() {
return "Table View";
return "Table";
}
@Override

View File

@ -353,7 +353,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer {
@Override
public String getTitle() {
return "Thumbnail View";
return "Thumbnail";
}
@Override

View File

@ -378,7 +378,9 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}
/**
*
* Return the types of mark up sources that this viewer knows about.
* Different sources will markup the text in different ways.
*
* @return currently available sources on the panel
*/
public List<MarkupSource> getSources() {
@ -390,7 +392,7 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}
/**
*
* Get the source selected in the combo box
* @return currently selected Source
*/
public MarkupSource getSelectedSource() {
@ -652,7 +654,8 @@ class ExtractedContentPanel extends javax.swing.JPanel {
}
/**
* Gets and sets new markup. Updates GUI in GUI thread and gets markup in
* Gets and sets new markup (i.e. based on user choose keyword hits or pure text).
* Updates GUI in GUI thread and gets markup in
* background thread. To be invoked from GUI thread only.
*/
private void setMarkup(MarkupSource source) {

View File

@ -81,20 +81,23 @@ public class ExtractedContentViewer implements DataContentViewer {
currentNode = selectedNode;
}
// sources are custom markup from the node (if available) and default
// markup is fetched from solr
/* Sources contain implementations that will markup the text
* in different ways. The original behavior for this was a source
* for the text markedup by SOLR and another that just displayed
* raw text.
*/
final List<MarkupSource> sources = new ArrayList<MarkupSource>();
//add additional registered sources for this node
sources.addAll(selectedNode.getLookup().lookupAll(MarkupSource.class));
if (!solrHasContent(selectedNode)) {
//currentNode = null;
//resetComponent();
// first source will be the default displayed
// if it doesn't have any SOLR content, then we won't add more sources
if (solrHasContent(selectedNode) == false) {
setPanel(sources);
return;
}
Content content = selectedNode.getLookup().lookup(Content.class);
if (content == null) {
return;
@ -103,6 +106,8 @@ public class ExtractedContentViewer implements DataContentViewer {
//add to page tracking if not there yet
final long contentID = content.getId();
// make a new source for the raw content
// @@@ BC: Why isn't this its own class like Highlight?
final MarkupSource newSource = new MarkupSource() {
private boolean inited = false;
private int numPages = 0;
@ -259,7 +264,7 @@ public class ExtractedContentViewer implements DataContentViewer {
@Override
public String getTitle() {
return "Text View";
return "Text";
}
@Override
@ -289,6 +294,8 @@ public class ExtractedContentViewer implements DataContentViewer {
public void resetComponent() {
setPanel(new ArrayList<MarkupSource>());
panel.resetDisplay();
currentNode = null;
currentSource = null;
}
@Override
@ -460,6 +467,11 @@ public class ExtractedContentViewer implements DataContentViewer {
@Override
public void actionPerformed(ActionEvent e) {
MarkupSource source = panel.getSelectedSource();
if (source == null) {
// reset
panel.updateControls(null);
return;
}
final boolean hasNextItem = source.hasNextItem();
final boolean hasNextPage = source.hasNextPage();
int indexVal = 0;
@ -552,6 +564,12 @@ public class ExtractedContentViewer implements DataContentViewer {
}
private void nextPage() {
// we should never have gotten here -- reset
if (currentSource == null) {
panel.updateControls(null);
return;
}
if (currentSource.hasNextPage()) {
currentSource.nextPage();
@ -579,6 +597,12 @@ public class ExtractedContentViewer implements DataContentViewer {
}
private void previousPage() {
// reset, we should have never gotten here if null
if (currentSource == null) {
panel.updateControls(null);
return;
}
if (currentSource.hasPreviousPage()) {
currentSource.previousPage();

View File

@ -46,7 +46,7 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup {
private static final String HIGHLIGHT_PRE = "<span style='background:yellow'>";
private static final String HIGHLIGHT_POST = "</span>";
private static final String ANCHOR_PREFIX = HighlightedMatchesSource.class.getName() + "_";
private static final String NO_MATCHES = "<span style='background:red'>No matches in content.</span>";
private static final String NO_MATCHES = "<span style='background:yellow'>There were no keyword hits on this page. <br />Advance to another page for hits or choose Extracted Text to view original text..</span>";
private Content content;
private String keywordHitQuery;
private Server solrServer;

View File

@ -21,8 +21,10 @@ package org.sleuthkit.autopsy.keywordsearch;
import java.util.LinkedHashMap;
/**
* Interface to provide HTML markup (to be displayed in ExtractedContentViewer)
* in a Node's lookup
* Interface to provide HTML text to display in ExtractedContentViewer.
* There is a SOLR implementaiton of this that interfaces with SOLR to
* highlight the keyword hits and a version that does not do markup
* so that you can simply view the stored text.
*/
public interface MarkupSource {

View File

@ -25,7 +25,6 @@ package org.sleuthkit.autopsy.recentactivity;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
@ -39,7 +38,7 @@ abstract public class Extract extends IngestModuleDataSource{
protected Case currentCase = Case.getCurrentCase(); // get the most updated case
protected SleuthkitCase tskCase = currentCase.getSleuthkitCase();
public final Logger logger = Logger.getLogger(this.getClass().getName());
protected final ArrayList<String> errorMessages = new ArrayList<String>();
protected final ArrayList<String> errorMessages = new ArrayList<>();
protected String moduleName = "";
//hide public constructor to prevent from instantiation by ingest module loader
@ -47,10 +46,23 @@ abstract public class Extract extends IngestModuleDataSource{
}
/**
* Returns a List of string error messages from the inheriting class
* @return errorMessages returns all error messages logged
*/
List<String> getErrorMessages() {
return errorMessages;
}
/**
* Adds a string to the error message list
*
* @param message is an error message represented as a string
*/
protected void addErrorMessage(String message) {
errorMessages.add(message);
}
/**
* Generic method for adding a blackboard artifact to the blackboard
@ -120,25 +132,10 @@ abstract public class Extract extends IngestModuleDataSource{
return list;
}
/**
* Returns a List of string error messages from the inheriting class
* @return errorMessages returns all error messages logged
*/
public ArrayList<String> getErrorMessage() {
return errorMessages;
}
/**
* Adds a string to the error message list
*
* @param message is an error message represented as a string
*/
public void addErrorMessage(String message) {
errorMessages.add(message);
}
/**
/**
* Returns the name of the inheriting class
* @return Gets the moduleName set in the moduleName data member
*/

View File

@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2012 Basis Technology Corp.
* Copyright 2012-2013 Basis Technology Corp.
*
* Copyright 2012 42six Solutions.
* Contact: aebadirad <at> 42six <dot> com
@ -35,12 +35,10 @@ import java.io.Writer;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.logging.Level;
import org.sleuthkit.autopsy.coreutils.Logger;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -52,7 +50,6 @@ import org.sleuthkit.autopsy.coreutils.EscapeUtil;
import org.sleuthkit.autopsy.coreutils.JLNK;
import org.sleuthkit.autopsy.coreutils.JLnkParser;
import org.sleuthkit.autopsy.datamodel.ContentUtils;
import org.sleuthkit.autopsy.datamodel.KeyValue;
import org.sleuthkit.autopsy.ingest.IngestDataSourceWorkerController;
import org.sleuthkit.autopsy.ingest.IngestServices;
import org.sleuthkit.autopsy.ingest.ModuleDataEvent;
@ -61,7 +58,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.autopsy.coreutils.PlatformUtil;
import org.sleuthkit.autopsy.ingest.PipelineContext;
import org.sleuthkit.autopsy.ingest.IngestModuleDataSource;
@ -69,24 +65,16 @@ import org.sleuthkit.autopsy.ingest.IngestModuleInit;
import org.sleuthkit.datamodel.*;
public class ExtractIE extends Extract {
private static final Logger logger = Logger.getLogger(ExtractIE.class.getName());
private IngestServices services;
private String recentQuery = "select * from `tsk_files` where parent_path LIKE '%/Recent%' and name LIKE '%.lnk'";
//sleauthkit db handle
SleuthkitCase tskCase;
//paths set in init()
private String PASCO_RESULTS_PATH;
private String moduleTempResultsDir;
private String PASCO_LIB_PATH;
private String JAVA_PATH;
//Results List to be referenced/used outside the class
public ArrayList<HashMap<String, Object>> PASCO_RESULTS_LIST = new ArrayList<HashMap<String, Object>>();
// List of Pasco result files for this data source
private List<String> pascoResults;
//Look Up Table that holds Pasco2 results
private HashMap<String, Object> PASCO_RESULTS_LUT;
private KeyValue IE_PASCO_LUT = new KeyValue(BrowserType.IE.name(), BrowserType.IE.getType());
public LinkedHashMap<String, Object> IE_OBJ;
boolean pascoFound = false;
final public static String MODULE_VERSION = "1.0";
private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
@ -96,6 +84,8 @@ public class ExtractIE extends Extract {
//hide public constructor to prevent from instantiation by ingest module loader
ExtractIE() {
moduleName = "Internet Explorer";
moduleTempResultsDir = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "IE") + File.separator + "results";
JAVA_PATH = PlatformUtil.getJavaPath();
}
@Override
@ -106,11 +96,52 @@ public class ExtractIE extends Extract {
@Override
public void process(PipelineContext<IngestModuleDataSource>pipelineContext, Content dataSource, IngestDataSourceWorkerController controller) {
this.getHistory(dataSource, controller);
this.getBookmark(dataSource, controller);
this.getCookie(dataSource, controller);
this.getRecentDocuments(dataSource, controller);
this.parsePascoResults(pascoResults);
/* @@@ BC: All of these try / catches are added because the exception
* handing in here isn't the best. We were losing results before because
* cookies was throwing an exceptionb ecause of an invalid URL and we
* skipped the rest of the data types. Need to push this eror handling
* further down though.
*/
try {
this.extractAndRunPasco(dataSource, controller);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Error extracting IE index.dat files", e);
addErrorMessage("Error extracting and analyzing IE index.dat files");
}
try {
this.getBookmark(dataSource, controller);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Error parsing IE bookmarks", e);
addErrorMessage("Error parsing IE bookmarks");
}
try {
this.getCookie(dataSource, controller);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Error parsing IE cookies", e);
addErrorMessage("Error parsing IE Cookies");
}
try {
this.getRecentDocuments(dataSource, controller);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Error parsing IE Recent Docs", e);
addErrorMessage("Error parsing IE Recent Documents");
}
try {
this.parsePascoResults(pascoResults);
}
catch (Exception e) {
logger.log(Level.SEVERE, "Error parsing IE History", e);
addErrorMessage("Error parsing IE History");
}
}
//Favorites section
@ -273,20 +304,11 @@ public class ExtractIE extends Extract {
services.fireModuleDataEvent(new ModuleDataEvent("Recent Activity", BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT));
}
//@Override
public KeyValue getRecentActivity() {
return IE_PASCO_LUT;
}
private void getHistory(Content dataSource, IngestDataSourceWorkerController controller) {
currentCase = Case.getCurrentCase();
tskCase = currentCase.getSleuthkitCase();
PASCO_RESULTS_PATH = RAImageIngestModule.getRATempPath(Case.getCurrentCase(), "IE") + File.separator + "results";
JAVA_PATH = PlatformUtil.getJavaPath();
private void extractAndRunPasco(Content dataSource, IngestDataSourceWorkerController controller) {
pascoResults = new ArrayList<String>();
logger.log(Level.INFO, "Pasco results path: " + PASCO_RESULTS_PATH);
logger.log(Level.INFO, "Pasco results path: " + moduleTempResultsDir);
final File pascoRoot = InstalledFileLocator.getDefault().locate("pasco2", ExtractIE.class.getPackage().getName(), false);
if (pascoRoot == null) {
@ -303,7 +325,7 @@ public class ExtractIE extends Extract {
PASCO_LIB_PATH = pascoHome + File.separator + "pasco2.jar" + File.pathSeparator
+ pascoHome + File.separator + "*";
File resultsDir = new File(PASCO_RESULTS_PATH);
File resultsDir = new File(moduleTempResultsDir);
resultsDir.mkdirs();
@ -365,7 +387,7 @@ public class ExtractIE extends Extract {
Writer writer = null;
try {
final String pascoOutFile = PASCO_RESULTS_PATH + File.separator + filename;
final String pascoOutFile = moduleTempResultsDir + File.separator + filename;
logger.log(Level.INFO, "Writing pasco results to: " + pascoOutFile);
writer = new FileWriter(pascoOutFile);
execPasco = new ExecUtil();
@ -400,11 +422,7 @@ public class ExtractIE extends Extract {
}
// First thing we want to do is check to make sure the results directory
// is not empty.
File rFile = new File(PASCO_RESULTS_PATH);
//Let's make sure our list and lut are empty.
//PASCO_RESULTS_LIST.clear();
File rFile = new File(moduleTempResultsDir);
if (rFile.exists()) {
//Give me a list of pasco results in that directory
@ -418,7 +436,6 @@ public class ExtractIE extends Extract {
continue;
}
long artObjId = Long.parseLong(fileName.substring(fileName.indexOf(".") + 1, fileName.lastIndexOf(".")));
//bbartname = bbartname.substring(0, 4);
// Make sure the file the is not empty or the Scanner will
// throw a "No Line found" Exception
@ -429,29 +446,28 @@ public class ExtractIE extends Extract {
fileScanner.nextLine();
fileScanner.nextLine();
fileScanner.nextLine();
// long inIndexId = 0;
while (fileScanner.hasNext()) {
//long bbartId = Long.parseLong(bbartname + inIndexId++);
String line = fileScanner.nextLine();
//Need to change this pattern a bit because there might
//be instances were "V" might not apply.
String pattern = "(?)URL(\\s)(V|\\:)";
Pattern p = Pattern.compile(pattern);
Matcher m = p.matcher(line);
if (m.find()) {
if (line.startsWith("URL")) {
String[] lineBuff = line.split("\\t");
PASCO_RESULTS_LUT = new HashMap<String, Object>();
String url[] = lineBuff[1].split("@", 2);
if (lineBuff.length < 4) {
// @@@ Could log a message here
continue;
}
String ddtime = lineBuff[2];
String actime = lineBuff[3];
Long ftime = (long) 0;
String user = "";
String realurl = "";
String domain = "";
if (url.length > 1) {
if (lineBuff[1].contains("@")) {
String url[] = lineBuff[1].split("@", 2);
user = url[0];
user = user.replace("Visited:", "");
user = user.replace(":Host:", "");
@ -462,12 +478,19 @@ public class ExtractIE extends Extract {
realurl = realurl.replaceAll(":(.*?):", "");
realurl = realurl.replace(":Host:", "");
realurl = realurl.trim();
domain = Util.extractDomain(realurl);
}
else {
user = "";
realurl = lineBuff[1].trim();
}
domain = Util.extractDomain(realurl);
if (!ddtime.isEmpty()) {
ddtime = ddtime.replace("T", " ");
ddtime = ddtime.substring(ddtime.length() - 5);
}
if (!actime.isEmpty()) {
try {
Long epochtime = dateFormatter.parse(actime).getTime();
@ -478,7 +501,6 @@ public class ExtractIE extends Extract {
}
}
// TODO: Need to fix this so we have the right obj_id
try {
BlackboardArtifact bbart = tskCase.getContentById(artObjId).newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY);
Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>();
@ -497,27 +519,19 @@ public class ExtractIE extends Extract {
bbart.addAttributes(bbattributes);
} catch (TskCoreException ex) {
logger.log(Level.SEVERE, "Error writing Internet Explorer web history artifact to the blackboard.", ex);
}
//KeyValueThing
//This will be redundant in terms IE.name() because of
//the way they implemented KeyValueThing
IE_OBJ = new LinkedHashMap<String, Object>();
IE_OBJ.put(BrowserType.IE.name(), PASCO_RESULTS_LUT);
IE_PASCO_LUT.addMap(IE_OBJ);
PASCO_RESULTS_LIST.add(PASCO_RESULTS_LUT);
}
}
else {
// @@@ Log that we didn't parse this
}
}
} catch (FileNotFoundException ex) {
logger.log(Level.WARNING, "Unable to find the Pasco file at " + file.getPath(), ex);
}
}
//TODO: Fix Delete issue
boolean bDelete = file.delete();
}
}
}
@ -532,8 +546,8 @@ public class ExtractIE extends Extract {
@Override
public void complete() {
// Delete all the results when complete
for (String file : pascoResults) {
String filePath = PASCO_RESULTS_PATH + File.separator + file;
/*for (String file : pascoResults) {
String filePath = moduleTempResultsDir + File.separator + file;
try {
File f = new File(filePath);
if (f.exists() && f.canWrite()) {
@ -545,6 +559,7 @@ public class ExtractIE extends Extract {
logger.log(Level.WARNING, "Incorrect permission to delete file " + filePath, ex);
}
}
*/
pascoResults.clear();
logger.info("Internet Explorer extract has completed.");
}
@ -556,7 +571,6 @@ public class ExtractIE extends Extract {
execPasco = null;
}
//call regular cleanup from complete() method
complete();
}
@ -570,4 +584,4 @@ public class ExtractIE extends Extract {
public boolean hasBackgroundJobsRunning() {
return false;
}
}
}

View File

@ -71,11 +71,13 @@ public final class RAImageIngestModule extends IngestModuleDataSource {
logger.log(Level.INFO, "Recent Activity has been canceled, quitting before {0}", module.getName());
break;
}
try {
module.process(pipelineContext, dataSource, controller);
} catch (Exception ex) {
logger.log(Level.SEVERE, "Exception occurred in " + module.getName(), ex);
subCompleted.append(module.getName()).append(" failed - see log for details <br>");
errors.add(module.getName() + "had errors -- see log");
}
controller.progress(i + 1);
errors.addAll(module.getErrorMessages());
@ -84,7 +86,9 @@ public final class RAImageIngestModule extends IngestModuleDataSource {
// create the final message for inbox
StringBuilder errorMessage = new StringBuilder();
String errorMsgSubject;
if (!errors.isEmpty()) {
MessageType msgLevel = MessageType.INFO;
if (errors.isEmpty() == false) {
msgLevel = MessageType.ERROR;
errorMessage.append("<p>Errors encountered during analysis: <ul>\n");
for (String msg : errors) {
errorMessage.append("<li>").append(msg).append("</li>\n");
@ -100,7 +104,7 @@ public final class RAImageIngestModule extends IngestModuleDataSource {
errorMessage.append("<p>No errors encountered.</p>");
errorMsgSubject = "No errors reported";
}
final IngestMessage msg = IngestMessage.createMessage(++messageId, MessageType.INFO, this, "Finished " + dataSource.getName()+ " - " + errorMsgSubject, errorMessage.toString());
final IngestMessage msg = IngestMessage.createMessage(++messageId, msgLevel, this, "Finished " + dataSource.getName()+ " - " + errorMsgSubject, errorMessage.toString());
services.postMessage(msg);
}