diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java index 4aa6de6740..498b6b9771 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java @@ -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 allExt = new ArrayList(); - { + static { allExt.addAll(rawExt); allExt.addAll(encaseExt); } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java index 8c57567668..e25582a47d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/ImageFilePanel.java @@ -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); diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form new file mode 100755 index 0000000000..f5255ac1af --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.form @@ -0,0 +1,52 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java new file mode 100755 index 0000000000..cae2561fc8 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Metadata.java @@ -0,0 +1,189 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 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.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") + // //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) + ); + }// //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("" + str + ""); + } + + private void startTable(StringBuilder sb) { + sb.append(""); + } + + private void endTable(StringBuilder sb) { + sb.append("
"); + } + + private void addRow(StringBuilder sb, String key, String value) { + sb.append(""); + sb.append(key); + sb.append(""); + sb.append(value); + sb.append(""); + } + + @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; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/Utilities.java b/Core/src/org/sleuthkit/autopsy/contentviewers/Utilities.java new file mode 100755 index 0000000000..08203ff782 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/Utilities.java @@ -0,0 +1,49 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2013 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.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;}"); + } +} diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java index b56614bbc4..978c8dc079 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerArtifact.java @@ -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 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java index 1df9d11a96..0ec89f14ca 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerHex.java @@ -390,7 +390,7 @@ public class DataContentViewerHex extends javax.swing.JPanel implements DataCont @Override public String getTitle() { - return "Hex View"; + return "Hex"; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index af1d14d312..544bc6b85b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -162,7 +162,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo @Override public String getTitle() { - return "Media View"; + return "Media"; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java index c5bc6b9970..ed87edd1df 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerString.java @@ -443,7 +443,7 @@ public class DataContentViewerString extends javax.swing.JPanel implements DataC @Override public String getTitle() { - return "String View"; + return "Strings"; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 1b5440036d..36ccb8715d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -385,7 +385,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { @Override public String getTitle() { - return "Table View"; + return "Table"; } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index 496afb71c3..9c4fd31609 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -353,7 +353,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { @Override public String getTitle() { - return "Thumbnail View"; + return "Thumbnail"; } @Override diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java index b3faa3d974..828b046d6d 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentPanel.java @@ -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 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) { diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java index e27fff3ceb..66582a2852 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/ExtractedContentViewer.java @@ -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 sources = new ArrayList(); //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()); 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(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedMatchesSource.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedMatchesSource.java index 58a48b865c..d240424b64 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedMatchesSource.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/HighlightedMatchesSource.java @@ -46,7 +46,7 @@ class HighlightedMatchesSource implements MarkupSource, HighlightLookup { private static final String HIGHLIGHT_PRE = ""; private static final String HIGHLIGHT_POST = ""; private static final String ANCHOR_PREFIX = HighlightedMatchesSource.class.getName() + "_"; - private static final String NO_MATCHES = "No matches in content."; + private static final String NO_MATCHES = "There were no keyword hits on this page.
Advance to another page for hits or choose Extracted Text to view original text..
"; private Content content; private String keywordHitQuery; private Server solrServer; diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/MarkupSource.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/MarkupSource.java index 555cb894f5..45d044c9aa 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/MarkupSource.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/MarkupSource.java @@ -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 { diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java index 7b0877f3ff..b3a5a5fe2b 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Extract.java @@ -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 errorMessages = new ArrayList(); + protected final ArrayList 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 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 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 */ diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java index d0087a237e..0b00d47732 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2012-2013 Basis Technology Corp. * * Copyright 2012 42six Solutions. * Contact: aebadirad 42six 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> PASCO_RESULTS_LIST = new ArrayList>(); + // List of Pasco result files for this data source private List pascoResults; - //Look Up Table that holds Pasco2 results - private HashMap PASCO_RESULTS_LUT; - private KeyValue IE_PASCO_LUT = new KeyValue(BrowserType.IE.name(), BrowserType.IE.getType()); - public LinkedHashMap 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(PipelineContextpipelineContext, 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(); - 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 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 bbattributes = new ArrayList(); @@ -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(); - 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; } -} +} \ No newline at end of file diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java index d9385d2912..53e19ae32b 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestModule.java @@ -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
"); + 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("

Errors encountered during analysis:

    \n"); for (String msg : errors) { errorMessage.append("
  • ").append(msg).append("
  • \n"); @@ -100,7 +104,7 @@ public final class RAImageIngestModule extends IngestModuleDataSource { errorMessage.append("

    No errors encountered.

    "); 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); }