diff --git a/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 05f773a7846644e88ea23bd4f7ad15509eb76a13..9d7c3973ed7a0a816eb24e73bb672f5fba452a40 100644 --- a/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/DataModel/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -145,8 +145,6 @@ private static Lookup getLookups(BlackboardArtifact artifact) { private static Content getAssociatedContent(BlackboardArtifact artifact){ try { return artifact.getSleuthkitCase().getContentById(artifact.getObjectID()); - } catch (SQLException ex) { - logger.log(Level.WARNING, "SQL query threw exception", ex); } catch (TskException ex) { logger.log(Level.WARNING, "Getting file failed", ex); } diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java index 35be0170b404a89806ad2ef636cde47f70bf8e21..fffb10a3ca48a65a86dc0e448e24a4759834b6fb 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestService.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.hashdatabase; +import java.beans.PropertyChangeListener; import java.io.IOException; import java.sql.SQLException; import java.util.Collections; @@ -185,9 +186,6 @@ public ProcessResult process(FsContent fsContent) { // TODO: This shouldn't be at level INFO, but it needs to be to hide the popup logger.log(Level.INFO, "Couldn't analyze file " + name + " - see sleuthkit log for details", ex); ret = ProcessResult.ERROR; - } catch (SQLException ex) { - logger.log(Level.WARNING, "Error updating file known status in database", ex); - ret = ProcessResult.ERROR; } catch (IOException ex) { // TODO: This shouldn't be at level INFO, but it needs to be to hide the popup logger.log(Level.INFO, "Error reading file", ex); @@ -207,6 +205,11 @@ public boolean hasBackgroundJobsRunning() { return false; } + @Override + public boolean backgroundJobsCompleteListener(PropertyChangeListener l) { + return false; + } + @Override public boolean hasSimpleConfiguration() { return false; diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java index d1b837b729a89e3e4228c87dd1db6c54d1e37826..bf497be0952610597d5a6f7b5f44820c6ec69ff7 100755 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestManager.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.ingest; +import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.text.DateFormat; @@ -139,7 +140,7 @@ IngestServiceFsContent.ProcessResult getFsContentServiceResult(String serviceNam * @param images images to execute services on */ void execute(final List<IngestServiceAbstract> services, final List<Image> images) { - logger.log(Level.INFO, "Will enqueue number of images: " + images.size()); + logger.log(Level.INFO, "Will enqueue number of images: " + images.size() + " to " + services.size() + " services."); if (!isIngestRunning()) { ui.clearMessages(); @@ -443,8 +444,9 @@ public void run() { */ public static List<IngestServiceImage> enumerateImageServices() { List<IngestServiceImage> ret = new ArrayList<IngestServiceImage>(); - for (IngestServiceImage list : Lookup.getDefault().lookupAll(IngestServiceImage.class)) + for (IngestServiceImage list : Lookup.getDefault().lookupAll(IngestServiceImage.class)) { ret.add(list); + } return ret; } @@ -453,8 +455,9 @@ public static List<IngestServiceImage> enumerateImageServices() { */ public static List<IngestServiceFsContent> enumerateFsContentServices() { List<IngestServiceFsContent> ret = new ArrayList<IngestServiceFsContent>(); - for (IngestServiceFsContent list : Lookup.getDefault().lookupAll(IngestServiceFsContent.class)) + for (IngestServiceFsContent list : Lookup.getDefault().lookupAll(IngestServiceFsContent.class)) { ret.add(list); + } return ret; } @@ -750,7 +753,7 @@ private QueueUnit<FsContent, IngestServiceFsContent> findFsContent(FsContent fsC public synchronized String toString() { return "FsContentQueue, size: " + Integer.toString(fsContentUnits.size()); } - + public String printQueue() { StringBuilder sb = new StringBuilder(); for (QueueUnit<FsContent, IngestServiceFsContent> u : fsContentUnits) { @@ -903,7 +906,7 @@ public int hashCode() { hash = 37 * hash + (this.services != null ? this.services.hashCode() : 0); return hash; } - + @Override public String toString() { StringBuilder sb = new StringBuilder(); @@ -957,14 +960,10 @@ public String toString() { public String toHtmlString() { StringBuilder sb = new StringBuilder(); sb.append("<html>"); - if (startTime != null) { - sb.append("Start time: ").append(dateFormatter.format(startTime)).append("<br />"); - } - if (endTime != null) { - sb.append("End time: ").append(dateFormatter.format(endTime)).append("<br />"); - } - sb.append("Total ingest time: ").append(getTotalTimeString()).append("<br />"); + + sb.append("Ingest time: ").append(getTotalTimeString()).append("<br />"); sb.append("Total errors: ").append(errorsTotal).append("<br />"); + /* if (errorsTotal > 0) { sb.append("Errors per service:"); for (IngestServiceAbstract service : errors.keySet()) { @@ -972,6 +971,8 @@ public String toHtmlString() { sb.append("\t").append(service.getName()).append(": ").append(errorsService).append("<br />"); } } + * */ + sb.append("</html>"); return sb.toString(); } @@ -1134,18 +1135,63 @@ protected void done() { handleInterruption(); logger.log(Level.SEVERE, "Fatal error during ingest.", ex); } finally { - stats.end(); + //stats.end(); progress.finish(); if (!this.isCancelled()) { - logger.log(Level.INFO, "Summary Report: " + stats.toString()); - ui.displayReport(stats.toHtmlString()); + //logger.log(Level.INFO, "Summary Report: " + stats.toString()); + //ui.displayReport(stats.toHtmlString()); + new FsServicesComplete(stats); } initMainProgress(0); } } + /** + * Ensures that all background threads are done + * then finalize the stats and show dialog + */ + private class FsServicesComplete { + + private IngestManagerStats stats; //ongoing stats + private List<IngestServiceAbstract> running = new ArrayList<IngestServiceAbstract>(); + + FsServicesComplete(IngestManagerStats stats) { + this.stats = stats; + + for (IngestServiceAbstract s : fsContentServices) { + if (s.backgroundJobsCompleteListener(new PropertyChangeListener() { + + @Override + public void propertyChange(PropertyChangeEvent evt) { + if (evt.getPropertyName().equals(IngestServiceAbstract.BCKGRND_JOBS_COMPLETED_EVT)) { + IngestServiceAbstract service = (IngestServiceAbstract) evt.getNewValue(); + running.remove(service); + if (running.isEmpty()) { + showStats(); + } + } + } + })) { + running.add(s); + } + } + + //no listeners registered since no services running any longer + if (running.isEmpty()) { + showStats(); + } + + } + + void showStats() { + stats.end(); + logger.log(Level.INFO, "Summary Report: " + stats.toString()); + ui.displayReport(stats.toHtmlString()); + } + } + private void handleInterruption() { for (IngestServiceFsContent s : fsContentServices) { s.stop(); @@ -1254,9 +1300,9 @@ private void queueAll(List<IngestServiceAbstract> services, final List<Image> im progress.progress(serviceName + " " + imageName, ++processed); } } - + //logger.log(Level.INFO, fsContentQueue.printQueue()); - + progress.progress("Sorting files", processed); sortFsContents(); } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java index 64792b87230018ed054cbcb1122c374147b9a20f..b53fe8da17b2bb6fc4015e10de5da47853695289 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessagePanel.java @@ -555,7 +555,7 @@ static class IngestMessageGroup { static Color VERY_HIGH_PRI_COLOR = new Color(164, 164, 202); //for a single message in a group static Color HIGH_PRI_COLOR = new Color(180, 180, 211); - static Color MED_PRI_COLOR = new Color(199, 199, 202); + static Color MED_PRI_COLOR = new Color(199, 199, 222); static Color LOW_PRI_COLOR = new Color(221, 221, 235); private List<IngestMessage> messages; private int count; diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java index bb6f3213e184160b18398aa82f093aa405956155..192ecdcf6dd937a223a6a316261a8429deaaac55 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestMessageTopComponent.java @@ -20,13 +20,15 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; -import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.Action; import javax.swing.BoxLayout; import javax.swing.JOptionPane; import org.openide.util.ImageUtilities; import org.openide.util.NbBundle; +import org.openide.util.Utilities; import org.openide.windows.Mode; import org.openide.windows.TopComponent; import org.openide.windows.WindowManager; @@ -103,22 +105,22 @@ public void componentOpened() { if (manager == null) { manager = IngestManager.getDefault(); } - + } @Override public void componentClosed() { //logger.log(Level.INFO, "CLOSED"); super.componentClosed(); - + /* Mode mode = WindowManager.getDefault().findMode("dockedBottom"); if (mode != null) { - mode.dockInto(this); - this.open(); + mode.dockInto(this); + this.open(); } * */ - + //this.close(); } @@ -126,7 +128,7 @@ public void componentClosed() { protected void componentShowing() { //logger.log(Level.INFO, "SHOWING"); super.componentShowing(); - + Mode mode = WindowManager.getDefault().findMode("floatingLeftBottom"); if (mode != null) { TopComponent[] tcs = mode.getTopComponents(); @@ -138,7 +140,7 @@ protected void componentShowing() { } mode.dockInto(this); this.open(); - } + } } @Override @@ -151,7 +153,7 @@ protected void componentHidden() { @Override protected void componentActivated() { //logger.log(Level.INFO, "ACTIVATED"); - super.componentActivated(); + super.componentActivated(); } @Override @@ -226,11 +228,40 @@ private void customizeComponents() { */ @Override public void displayReport(String ingestReport) { - JOptionPane.showMessageDialog( - null, + + Object[] options = {"OK", + "Generate Report"}; + final int choice = JOptionPane.showOptionDialog(null, ingestReport, - "File Ingest Summary", - JOptionPane.INFORMATION_MESSAGE); + "Ingest Report", + JOptionPane.YES_NO_OPTION, + JOptionPane.INFORMATION_MESSAGE, + null, + options, + options[0]); + + final String reportActionName = "org.sleuthkit.autopsy.report.reportAction"; + Action reportAction = null; + + //find action by name from action lookup, without introducing cyclic dependency + if (choice == JOptionPane.NO_OPTION) { + List<? extends Action> actions = Utilities.actionsForPath("Toolbars/File"); + for (Action a : actions) { + //separators are null actions + if (a != null) { + if (a.getClass().getCanonicalName().equals(reportActionName)) { + reportAction = a; + break; + } + } + } + + if (reportAction == null) + logger.log(Level.SEVERE, "Could not locate Action: " + reportActionName); + else reportAction.actionPerformed(null); + + } + } /** @@ -261,7 +292,6 @@ public void displayIngestDialog(final Image image) { ingestDialog.setImage(image); ingestDialog.display(); */ - } @Override diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java index fb67fec0ef2127f7c831e59ad72ed0ce35030697..b8ffdf756fdd516dcf9961fe101de0095e3134a8 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/IngestServiceAbstract.java @@ -19,12 +19,15 @@ package org.sleuthkit.autopsy.ingest; +import java.beans.PropertyChangeListener; + /** * Base interface for ingest services */ public interface IngestServiceAbstract { public enum ServiceType {Image, FsContent}; + public static final String BCKGRND_JOBS_COMPLETED_EVT = "BCKGRND_JOBS_COMPLETED_EVT"; /** * notification from manager that brand new processing should be initiated. @@ -61,11 +64,28 @@ public enum ServiceType {Image, FsContent}; /** * A service can manage and use additional threads to perform some work in the background. * This method provides insight to the manager if the service has truly completed its work or not. + * + * * @return true if any background threads/workers managed by this service are still running - * false if all work has been done, or if background threads are not used by this service + * false if all work has been done, or if background threads are not managed by this service */ public boolean hasBackgroundJobsRunning(); + /** + * Register listener to notify when all background jobs managed by this service have completed and the service + * has truly finished. The service should first check if it has threads running, and then register the listener, all in a single atomic, synchronized operation, and return the result of the registration. + * Do not register the listener if the background threads are not running and will not run during this service invocation. + * If the service does use background threads it is required to implement this method properly and ensure the event is fired when the service-managed threads complete (are finished or cancelled) + * The event fired off should be IngestServiceAbstract.BCKGRND_JOBS_COMPLETED_EVT, with the instance of IngestServiceAbstract in the newValue parameter. + * The listeners should be reset at service init() - listeners are expected to register again as needed during the new service run. + * Typical use case is for ingest manager to try to register the listener for every service when the queue has been consumed, + * for a precise indication when all work is truly done. + * + * @param l listener + * @return true if listener registered, false otherwise (i.e. no background jobs were running, or the service does not manage additional threads) + */ + public boolean backgroundJobsCompleteListener(PropertyChangeListener l); + /** * @return does this service have a simple configuration? diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleFsContentIngestService.java b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleFsContentIngestService.java index 41bc0b9f678c2336498bcf73f90093c8c7baced6..8819b72357dadd3766a473c311e63f7ae4d21bda 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleFsContentIngestService.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleFsContentIngestService.java @@ -18,9 +18,9 @@ */ package org.sleuthkit.autopsy.ingest.example; +import java.beans.PropertyChangeListener; import java.util.logging.Level; import java.util.logging.Logger; -import javax.swing.JPanel; import org.sleuthkit.autopsy.ingest.IngestManagerProxy; import org.sleuthkit.autopsy.ingest.IngestMessage; import org.sleuthkit.autopsy.ingest.IngestMessage.MessageType; @@ -117,6 +117,11 @@ public boolean hasBackgroundJobsRunning() { return false; } + @Override + public boolean backgroundJobsCompleteListener(PropertyChangeListener l) { + return false; + } + @Override public void saveAdvancedConfiguration() { } diff --git a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java index ae38dbf2eea05eee92217659944c04d125e77963..73ab81203440ef17ca9b0ac08b9b37325df43f09 100644 --- a/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java +++ b/Ingest/src/org/sleuthkit/autopsy/ingest/example/ExampleImageIngestService.java @@ -18,6 +18,7 @@ */ package org.sleuthkit.autopsy.ingest.example; +import java.beans.PropertyChangeListener; import java.util.logging.Level; import java.util.logging.Logger; import org.sleuthkit.autopsy.ingest.IngestImageWorkerController; @@ -147,6 +148,11 @@ public boolean hasBackgroundJobsRunning() { return false; } + @Override + public boolean backgroundJobsCompleteListener(PropertyChangeListener l) { + return false; + } + @Override public void saveAdvancedConfiguration() { } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java index 8a7c5ef0420219d756b5cc322379058b2ec604ba..48c5f07340c2e2ffd73670be5cc24c332ddf6a4c 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Ingester.java @@ -48,6 +48,7 @@ class Ingester { } @Override + @SuppressWarnings("FinalizeDeclaration") protected void finalize() throws Throwable { super.finalize(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java index d0f7e2096bba9b6bf8f401d1ad9dc7f417e674a2..c9228d544a80a3eb5bdc81968bf6bf64651acb96 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchEditListPanel.java @@ -844,7 +844,7 @@ void deleteSelected(int[] selected) { } - class TableEntry implements Comparable { + class TableEntry implements Comparable<TableEntry> { Keyword keyword; @@ -853,12 +853,12 @@ class TableEntry implements Comparable { } @Override - public int compareTo(Object o) { - int keywords = this.keyword.getQuery().compareTo(((TableEntry) o).keyword.getQuery()); + public int compareTo(TableEntry te) { + int keywords = this.keyword.getQuery().compareTo(te.keyword.getQuery()); if (keywords != 0) { return keywords; } else { - return Boolean.valueOf(keyword.isLiteral()).compareTo(((TableEntry) o).keyword.isLiteral()); + return Boolean.valueOf(keyword.isLiteral()).compareTo(te.keyword.isLiteral()); } } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java index e9eada1663bcc525b685f734b73b49e5196b026a..3d64f4a671db499cf5d403408a9b4c901361d9ba 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestService.java @@ -18,6 +18,8 @@ */ package org.sleuthkit.autopsy.keywordsearch; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -25,7 +27,6 @@ import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import javax.swing.JPanel; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import org.apache.commons.lang.StringEscapeUtils; @@ -38,6 +39,7 @@ 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.IngestServiceFsContent; import org.sleuthkit.autopsy.ingest.ServiceDataEvent; import org.sleuthkit.autopsy.keywordsearch.Ingester.IngesterException; @@ -66,13 +68,17 @@ public final class KeywordSearchIngestService implements IngestServiceFsContent //private final Object lock = new Object(); private Thread timer; private Indexer indexer; - private SwingWorker searcher; + private Searcher searcher; private volatile boolean searcherDone = true; + private static PropertyChangeSupport pcs = null; private Map<Keyword, List<FsContent>> currentResults; private volatile int messageID = 0; + private boolean processedFiles; private volatile boolean finalRun = false; + private volatile boolean finalRunComplete = false; private final String hashDBServiceName = "Hash Lookup"; private SleuthkitCase caseHandle = null; + // TODO: use a more robust method than checking file extension to determine // whether to try a file // supported extensions list from http://www.lucidimagination.com/devzone/technical-articles/content-extraction-tika @@ -108,6 +114,9 @@ else if (hashDBResult == IngestServiceFsContent.ProcessResult.ERROR) { //notify depending service that keyword search (would) encountered error for this file return ProcessResult.ERROR; } + + if (processedFiles == false) + processedFiles = true; //check if time to commit and previous search is not running //commiting while searching causes performance issues @@ -151,11 +160,12 @@ public void complete() { updateKeywords(); //run one last search as there are probably some new files committed - if (keywords != null && !keywords.isEmpty()) { + if (keywords != null && !keywords.isEmpty() && processedFiles == true) { finalRun = true; searcher = new Searcher(keywords); searcher.execute(); } else { + finalRunComplete = true; managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, this, "Completed")); } //postSummary(); @@ -191,6 +201,9 @@ public void init(IngestManagerProxy managerProxy) { caseHandle = Case.getCurrentCase().getSleuthkitCase(); this.managerProxy = managerProxy; + + //this deregisters previously registered listeners at every init() + pcs = new PropertyChangeSupport(KeywordSearchIngestService.class); final Server.Core solrCore = KeywordSearch.getServer().getCore(); ingester = solrCore.getIngester(); @@ -209,7 +222,9 @@ public void init(IngestManagerProxy managerProxy) { managerProxy.postMessage(IngestMessage.createWarningMessage(++messageID, instance, "No keywords in keyword list.", "Only indexing will be done and and keyword search will be skipped (it can be executed later again as ingest or using toolbar search feature).")); } + processedFiles = false; finalRun = false; + finalRunComplete = false; searcherDone = true; //make sure to start the initial searcher //keeps track of all results per run not to repeat reporting the same hits currentResults = new HashMap<Keyword, List<FsContent>>(); @@ -271,6 +286,17 @@ public boolean hasBackgroundJobsRunning() { //no need to check timer thread } + + @Override + public synchronized boolean backgroundJobsCompleteListener(PropertyChangeListener l) { + if (finalRunComplete == true) + return false; + else { + pcs.addPropertyChangeListener(l); + return true; + } + + } private void commit() { ingester.commit(); @@ -468,16 +494,17 @@ private void processNonIngestible(FsContent fsContent) { if (fsContent.getSize() < MAX_STRING_EXTRACT_SIZE) { if (!extractAndIngest(fsContent)) { logger.log(Level.INFO, "Failed to extract strings and ingest, file '" + fsContent.getName() + "' (id: " + fsContent.getId() + ")."); + ingestStatus.put(fsContent.getId(), IngestStatus.SKIPPED); } else { ingestStatus.put(fsContent.getId(), IngestStatus.EXTRACTED_INGESTED); } } else { - ingestStatus.put(fsContent.getId(), IngestStatus.SKIPPED); + //ingestStatus.put(fsContent.getId(), IngestStatus.SKIPPED); } } } - private class Searcher extends SwingWorker { + private class Searcher extends SwingWorker<Object,Void> { private List<Keyword> keywords; private ProgressHandle progress; @@ -499,6 +526,7 @@ protected Object doInBackground() throws Exception { @Override public boolean cancel() { + finalRunComplete = true; return Searcher.this.cancel(true); } }); @@ -655,9 +683,11 @@ protected void done() { //logger.log(Level.INFO, "Finished search"); if (finalRun) { + finalRunComplete = true; keywords.clear(); keywordLists.clear(); managerProxy.postMessage(IngestMessage.createMessage(++messageID, MessageType.INFO, KeywordSearchIngestService.instance, "Completed")); + pcs.firePropertyChange(IngestServiceAbstract.BCKGRND_JOBS_COMPLETED_EVT, null, KeywordSearchIngestService.this); } } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java index 71f90cc2c2839c153d5cbcec195faed34eda6029..03e5ba8eef9573e281f1bb35228ead1b9adfcdb7 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsManagementPanel.java @@ -396,7 +396,7 @@ private void addLists(List<KeywordSearchList> lists) { } //single model entry - class TableEntry implements Comparable { + class TableEntry implements Comparable<TableEntry> { String name; @@ -405,8 +405,8 @@ class TableEntry implements Comparable { } @Override - public int compareTo(Object o) { - return this.name.compareTo(((TableEntry) o).name); + public int compareTo(TableEntry te) { + return this.name.compareTo(te.name); } } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java index 74c3fe83c073d299b9512c32cb795a4660729a03..db3f8db9ea994418ecdecbe8b14ec430d804d246 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchListsViewerPanel.java @@ -506,7 +506,7 @@ private void addLists(List<KeywordSearchList> lists) { } //single model entry - private class ListTableEntry implements Comparable { + private class ListTableEntry implements Comparable<ListTableEntry> { String name; Boolean selected; @@ -520,8 +520,8 @@ private class ListTableEntry implements Comparable { } @Override - public int compareTo(Object o) { - return this.name.compareTo(((ListTableEntry) o).name); + public int compareTo(ListTableEntry e) { + return this.name.compareTo(e.name); } } } @@ -606,7 +606,7 @@ void deleteAll() { } //single model entry - private class KeywordTableEntry implements Comparable { + private class KeywordTableEntry implements Comparable<KeywordTableEntry> { String name; Boolean regex; @@ -617,8 +617,8 @@ private class KeywordTableEntry implements Comparable { } @Override - public int compareTo(Object o) { - return this.name.compareTo(((KeywordTableEntry) o).name); + public int compareTo(KeywordTableEntry e) { + return this.name.compareTo(e.name); } } } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java index a9f8a4744e0becc77564456c716504ad368354f6..fc7abb5cce544dc1c139c94ea793fc0d415a5944 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchUtil.java @@ -131,7 +131,9 @@ public static boolean displayConfirmDialog(final String title, final String mess //TODO escaping should be handled by blackboard public static String escapeForBlackBoard(String text) { try { - text = text.replaceAll("\\\\'", URLEncoder.encode("\\'", "UTF-8")); + //text = text.replaceAll("\\\\'", URLEncoder.encode("\\'", "UTF-8")); + text = text.replaceAll("'", URLEncoder.encode("'", "UTF-8")); + //text = text.replaceAll("\"", URLEncoder.encode("\"", "UTF-8")); //text = text.replaceAll("\\\\", URLEncoder.encode("\\", "UTF-8")); } catch (UnsupportedEncodingException ex) { } diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermComponentQuery.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermComponentQuery.java index 819e7984eed62956babb694369abe139e96c8a41..f296739a34d8e61f3159fdcf839ad1cec3c263a2 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermComponentQuery.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/TermComponentQuery.java @@ -199,7 +199,8 @@ public Collection<KeywordWriteResult> writeToBlackBoard(FsContent newFsHit, Stri attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD_REGEXP.getTypeID(), MODULE_NAME, "", KeywordSearchUtil.escapeForBlackBoard(termsQuery))); //regex match - attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID(), MODULE_NAME, "", regexMatch)); + final String regexMatchEscaped = KeywordSearchUtil.escapeForBlackBoard(regexMatch); + attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_KEYWORD.getTypeID(), MODULE_NAME, "", regexMatchEscaped)); //list if (listName == null) { listName = ""; @@ -214,7 +215,7 @@ public Collection<KeywordWriteResult> writeToBlackBoard(FsContent newFsHit, Stri if (keywordQuery != null) { BlackboardAttribute.ATTRIBUTE_TYPE selType = keywordQuery.getType(); if (selType != null) { - BlackboardAttribute selAttr = new BlackboardAttribute(selType.getTypeID(), MODULE_NAME, "", regexMatch); + BlackboardAttribute selAttr = new BlackboardAttribute(selType.getTypeID(), MODULE_NAME, "", regexMatchEscaped); attributes.add(selAttr); } } @@ -297,7 +298,7 @@ public void execute() { logger.log(Level.INFO, "Executing TermsComponent query: " + q.toString()); - final SwingWorker worker = new TermsQueryWorker(q); + final SwingWorker<List<Term>, Void> worker = new TermsQueryWorker(q); worker.execute(); } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java index fad833d7a3e810b1e6432c3f25c9cdf7519b77c4..8bdee2792b4eb510668c9aaa27ebe8da457467a3 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Chrome.java @@ -31,6 +31,8 @@ public class Chrome { + "datetime(urls.last_visit_time/1000000-11644473600,'unixepoch','localtime') as last_visit_time, urls.hidden, visits.visit_time, visits.from_visit, visits.transition FROM urls, visits WHERE urls.id = visits.url"; public static final String chcookiequery = "select name, value, host, expires_utc, datetime(last_access_utc/1000000-11644473600,'unixepoch','localtime') as last_access_utc, creation_utc from cookies"; public static final String chbookmarkquery = "SELECT starred.title, urls.url, starred.date_added, starred.date_modified, urls.typed_count, datetime(urls.last_visit_time/1000000-11644473600,'unixepoch','localtime') as urls._last_visit_time FROM starred INNER JOIN urls ON urls.id = starred.url_id"; + public static final String chdownloadquery = "select full_path, url, start_time, received_bytes from `downloads`"; + public static final String chloginquery = "select origin_url, username_value, signon_realm from `logins`"; private final Logger logger = Logger.getLogger(this.getClass().getName()); public int ChromeCount = 0; @@ -82,7 +84,7 @@ public void getchdb(List<String> image, IngestImageWorkerController controller){ bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),"RecentActivity","",temprs.getString("url"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(),"RecentActivity","Last Accessed",temprs.getString("last_visit_time"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(),"RecentActivity","",temprs.getString("from_visit"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(),"RecentActivity","",((temprs.getString("title") != null) ? temprs.getString("title") : "No Title"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(),"RecentActivity","",((temprs.getString("title") != null) ? temprs.getString("title") : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","Chrome")); bbart.addAttributes(bbattributes); @@ -144,7 +146,7 @@ public void getchdb(List<String> image, IngestImageWorkerController controller){ bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", "", temprs.getString("host"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(),"RecentActivity", "Last Visited",temprs.getString("access_utc"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(),"RecentActivity", "",temprs.getString("value"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","Title",((temprs.getString("name") != null) ? temprs.getString("name") : "No name"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","Title",((temprs.getString("name") != null) ? temprs.getString("name") : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","Chrome")); bbart.addAttributes(bbattributes); } @@ -202,8 +204,132 @@ public void getchdb(List<String> image, IngestImageWorkerController controller){ BlackboardArtifact bbart = FFSqlitedb.get(j).newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK); Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(),"RecentActivity","Last Visited",temprs.getString("last_visit_time"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity","",((temprs.getString("url") != null) ? temprs.getString("url") : "No URL"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","", ((temprs.getString("title") != null) ? temprs.getString("title").replaceAll("'", "''") : "No Title"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity","",((temprs.getString("url") != null) ? temprs.getString("url") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","", ((temprs.getString("title") != null) ? temprs.getString("title").replaceAll("'", "''") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","Chrome")); + bbart.addAttributes(bbattributes); + + } + tempdbconnect.closeConnection(); + temprs.close(); + + } + catch (Exception ex) + { + logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex); + } + j++; + dbFile.delete(); + } + } + catch (SQLException ex) + { + logger.log(Level.WARNING, "Error while trying to get Chrome SQLite db.", ex); + } + catch(IOException ioex) + { + logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex); + } + + //Downloads section + // This gets the downloads info + try + { + Case currentCase = Case.getCurrentCase(); // get the most updated case + SleuthkitCase tempDb = currentCase.getSleuthkitCase(); + List<FsContent> FFSqlitedb; + ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE 'History' and parent_path LIKE '%Chrome%' and fs_obj_id = '" + image + "'"); + FFSqlitedb = tempDb.resultSetToFsContents(rs); + rs.close(); + rs.getStatement().close(); + + int j = 0; + + while (j < FFSqlitedb.size()) + { + String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"; + String connectionString = "jdbc:sqlite:" + temps; + ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db")); + File dbFile = new File(temps); + if (controller.isCancelled() ) { + dbFile.delete(); + break; + } + try + { + dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString); + ResultSet temprs = tempdbconnect.executeQry(chdownloadquery); + while(temprs.next()) + { + BlackboardArtifact bbart = FFSqlitedb.get(j).newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); + Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(),"RecentActivity","Last Visited",temprs.getString("start_time"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity","",((temprs.getString("url") != null) ? temprs.getString("url") : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","", ((temprs.getString("title") != null) ? temprs.getString("title").replaceAll("'", "''") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), "Recent Activity", "", temprs.getString("full_path"))); + + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","Chrome")); + bbart.addAttributes(bbattributes); + + } + tempdbconnect.closeConnection(); + temprs.close(); + + } + catch (Exception ex) + { + logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex); + } + j++; + dbFile.delete(); + } + } + catch (SQLException ex) + { + logger.log(Level.WARNING, "Error while trying to get Chrome SQLite db.", ex); + } + catch(IOException ioex) + { + logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex); + } + + //Login/Password section + // This gets the user info + try + { + Case currentCase = Case.getCurrentCase(); // get the most updated case + SleuthkitCase tempDb = currentCase.getSleuthkitCase(); + List<FsContent> FFSqlitedb; + ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE 'signons.sqlite' and parent_path LIKE '%Chrome%' and fs_obj_id = '" + image + "'"); + FFSqlitedb = tempDb.resultSetToFsContents(rs); + rs.close(); + rs.getStatement().close(); + + int j = 0; + + while (j < FFSqlitedb.size()) + { + String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"; + String connectionString = "jdbc:sqlite:" + temps; + ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db")); + File dbFile = new File(temps); + if (controller.isCancelled() ) { + dbFile.delete(); + break; + } + try + { + dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString); + ResultSet temprs = tempdbconnect.executeQry(chloginquery); + while(temprs.next()) + { + BlackboardArtifact bbart = FFSqlitedb.get(j).newArtifact(ARTIFACT_TYPE.TSK_WEB_HISTORY); + Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(),"RecentActivity","Last Visited",temprs.getString("start_time"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity","",((temprs.getString("origin_url") != null) ? temprs.getString("origin_url") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_USERNAME.getTypeID(), "RecentActivity","", ((temprs.getString("username_value") != null) ? temprs.getString("username_value").replaceAll("'", "''") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DOMAIN.getTypeID(), "Recent Activity", "", temprs.getString("signon_realm"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","Chrome")); bbart.addAttributes(bbattributes); diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractAll.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractAll.java index 84c03334567109be4fb8aa41169f0c48dcb02872..6cc7779ff54390661990af8e1f020730d34acef3 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractAll.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractAll.java @@ -14,7 +14,7 @@ public class ExtractAll { void ExtractAll(){ - + } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java index 1d3440d9400fd2e97a3357b15337ec791d2bdb98..1e0968b8d679e508245a50e5b796bc71528d8a93 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractIE.java @@ -292,9 +292,7 @@ public void parsePascoResults() { PASCO_RESULTS_LIST.add(PASCO_RESULTS_LUT); } catch (TskException ex) { Exceptions.printStackTrace(ex); - } catch (SQLException ex) { - logger.log(Level.WARNING, "Couldn't find file with id: " + artObjId, ex); - } + } } } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index e9fa80a8a9bfb8993b7ec826aa3631e065774075..366382e6b82e2d42cfd164806a15ffce4de86687 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -42,7 +42,7 @@ public class ExtractRegistry { public Logger logger = Logger.getLogger(this.getClass().getName()); private String RR_PATH; boolean rrFound = false; - + private int sysid; ExtractRegistry(){ final File rrRoot = InstalledFileLocator.getDefault().locate("rr", ExtractRegistry.class.getPackage().getName(), false); if (rrRoot == null) { @@ -53,7 +53,18 @@ public class ExtractRegistry { else { rrFound = true; } - + try{ + Case currentCase = Case.getCurrentCase(); // get the most updated case + SleuthkitCase tempDb = currentCase.getSleuthkitCase(); + ResultSet artset = tempDb.runQuery("SELECT * from blackboard_artifact_types WHERE type_name = 'TSK_SYS_INFO'"); + + while (artset.next()){ + sysid = artset.getInt("artifact_type_id"); + } + } + catch(Exception e){ + + } final String rrHome = rrRoot.getAbsolutePath(); logger.log(Level.INFO, "RegRipper home: " + rrHome); @@ -175,7 +186,9 @@ private boolean parseReg(String regRecord, long orgId) { Case currentCase = Case.getCurrentCase(); // get the most updated case SleuthkitCase tempDb = currentCase.getSleuthkitCase(); + try { + String regString = new Scanner(new File(regRecord)).useDelimiter("\\Z").next(); String startdoc = "<document>"; String result = regString.replaceAll("----------------------------------------",""); @@ -199,7 +212,7 @@ private boolean parseReg(String regRecord, long orgId) Element artroot = tempnode.getChild("artifacts"); List artlist = artroot.getChildren(); - BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(), "RecentActivity", context, time)); Iterator aiterator = artlist.iterator(); @@ -210,16 +223,27 @@ private boolean parseReg(String regRecord, long orgId) bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity", context, name)); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", context, value)); } - - - - + if("recentdocs".equals(context)){ + BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); bbart.addAttributes(bbattributes); + } + else if("runMRU".equals(context)){ + BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(ARTIFACT_TYPE.TSK_RECENT_OBJECT); + bbart.addAttributes(bbattributes); + + } + else + { + + BlackboardArtifact bbart = tempDb.getContentById(orgId).newArtifact(sysid); + bbart.addAttributes(bbattributes); + } + } } catch (Exception ex) { - String hi = ""; + logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + ex); } diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java index 2380a191eb35e25d9def2e7d25ee552c55393b47..47c27467ff64e4dedcaec3d5e0bee85d71328e52 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Firefox.java @@ -31,6 +31,7 @@ public class Firefox { private static final String ffquery = "SELECT moz_historyvisits.id,url,title,visit_count,datetime(moz_historyvisits.visit_date/1000000,'unixepoch','localtime') as visit_date,from_visit,(SELECT url FROM moz_places WHERE id=moz_historyvisits.from_visit) as ref FROM moz_places, moz_historyvisits WHERE moz_places.id = moz_historyvisits.place_id AND hidden = 0"; private static final String ffcookiequery = "SELECT name,value,host,expiry,datetime(moz_cookies.lastAccessed/1000000,'unixepoch','localtime') as lastAccessed,creationTime FROM moz_cookies"; private static final String ffbookmarkquery = "SELECT fk, moz_bookmarks.title, url FROM moz_bookmarks INNER JOIN moz_places ON moz_bookmarks.fk=moz_places.id"; + private static final String ffdownloadquery = "select target, source, startTime, maxBytes from `moz_downloads`"; public Logger logger = Logger.getLogger(this.getClass().getName()); @@ -88,8 +89,8 @@ public void getffdb(List<String> image, IngestImageWorkerController controller){ Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),"RecentActivity","",temprs.getString("url"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(),"RecentActivity","Last Visited",temprs.getString("visit_date"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(),"RecentActivity","",((temprs.getString("ref") != null) ? temprs.getString("ref") : "None"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(),"RecentActivity","",((temprs.getString("title") != null) ? temprs.getString("title") : "No Title"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_REFERRER.getTypeID(),"RecentActivity","",((temprs.getString("ref") != null) ? temprs.getString("ref") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(),"RecentActivity","",((temprs.getString("title") != null) ? temprs.getString("title") : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","FireFox")); bbart.addAttributes(bbattributes); @@ -100,8 +101,8 @@ public void getffdb(List<String> image, IngestImageWorkerController controller){ { BlackboardArtifact bbart = FFSqlitedb.get(j).newArtifact(ARTIFACT_TYPE.TSK_WEB_BOOKMARK); Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),"RecentActivity","",((temprs.getString("url") != null) ? temprs.getString("url") : "No URL"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","", ((temprs.getString("title") != null) ? temprs.getString("title").replaceAll("'", "''") : "No Title"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(),"RecentActivity","",((temprs.getString("url") != null) ? temprs.getString("url") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","", ((temprs.getString("title") != null) ? temprs.getString("title").replaceAll("'", "''") : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","FireFox")); bbart.addAttributes(bbattributes); } @@ -168,7 +169,7 @@ public void getffdb(List<String> image, IngestImageWorkerController controller){ bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity", "", temprs.getString("host"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), "RecentActivity", "Last Visited", temprs.getString("lastAccessed"))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_VALUE.getTypeID(), "RecentActivity", "", temprs.getString("value"))); - bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","Title",((temprs.getString("name") != null) ? temprs.getString("name") : "No name"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","Title",((temprs.getString("name") != null) ? temprs.getString("name") : ""))); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","FireFox")); bbart.addAttributes(bbattributes); @@ -193,6 +194,69 @@ public void getffdb(List<String> image, IngestImageWorkerController controller){ { logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex); } + + + //Downloads section + // This gets the downloads info + try + { + Case currentCase = Case.getCurrentCase(); // get the most updated case + SleuthkitCase tempDb = currentCase.getSleuthkitCase(); + List<FsContent> FFSqlitedb; + ResultSet rs = tempDb.runQuery("select * from tsk_files where name LIKE 'downloads.sqlite' and parent_path LIKE '%Firefox%' and fs_obj_id = '" + image + "'"); + FFSqlitedb = tempDb.resultSetToFsContents(rs); + rs.close(); + rs.getStatement().close(); + + int j = 0; + + while (j < FFSqlitedb.size()) + { + String temps = currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db"; + String connectionString = "jdbc:sqlite:" + temps; + ContentUtils.writeToFile(FFSqlitedb.get(j), new File(currentCase.getTempDirectory() + "\\" + FFSqlitedb.get(j).getName().toString() + j + ".db")); + File dbFile = new File(temps); + if (controller.isCancelled() ) { + dbFile.delete(); + break; + } + try + { + dbconnect tempdbconnect = new dbconnect("org.sqlite.JDBC",connectionString); + ResultSet temprs = tempdbconnect.executeQry(ffdownloadquery); + while(temprs.next()) + { + BlackboardArtifact bbart = FFSqlitedb.get(j).newArtifact(ARTIFACT_TYPE.TSK_WEB_DOWNLOAD); + Collection<BlackboardAttribute> bbattributes = new ArrayList<BlackboardAttribute>(); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_LAST_ACCESSED.getTypeID(),"RecentActivity","Last Visited",temprs.getString("startTime"))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_URL.getTypeID(), "RecentActivity","",((temprs.getString("source") != null) ? temprs.getString("source") : ""))); + //bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), "RecentActivity","", ((temprs.getString("title") != null) ? temprs.getString("title").replaceAll("'", "''") : ""))); + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH.getTypeID(), "Recent Activity", "", temprs.getString("target"))); + + bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(),"RecentActivity","","Chrome")); + bbart.addAttributes(bbattributes); + + } + tempdbconnect.closeConnection(); + temprs.close(); + + } + catch (Exception ex) + { + logger.log(Level.WARNING, "Error while trying to read into a sqlite db." + connectionString, ex); + } + j++; + dbFile.delete(); + } + } + catch (SQLException ex) + { + logger.log(Level.WARNING, "Error while trying to get FireFox SQLite db.", ex); + } + catch(IOException ioex) + { + logger.log(Level.WARNING, "Error while trying to write to the file system.", ioex); + } } } //@Override diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestService.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestService.java index 9e9332bf8ef48591870310ff3fa86825848d5f36..02526d349ecad80ab1e9717c66159aa8e10fcc8f 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestService.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RAImageIngestService.java @@ -18,12 +18,13 @@ */ package org.sleuthkit.autopsy.recentactivity; +import java.beans.PropertyChangeListener; +import java.sql.ResultSet; import java.util.Collection; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; -import javax.swing.JPanel; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.ingest.IngestImageWorkerController; import org.sleuthkit.autopsy.ingest.IngestManager; @@ -80,7 +81,28 @@ public void process(Image image, IngestImageWorkerController controller) { try { //do the work for(FileSystem img : imageFS ) - + try{ + ResultSet artset = sCurrentCase.runQuery("SELECT * from blackboard_artifact_types WHERE type_name = 'TSK_SYS_INFO'"); + int artcount = 0; + while (artset.next()){ + artcount++; + } + + // artset.beforeFirst(); + if(artcount > 0) + { + + } + else + { + int artint = sCurrentCase.addArtifactType("TSK_SYS_INFO", "System Information"); + } + + } + catch(Exception e) + { + + } ext.extractToBlackboard(controller, fsIds); @@ -162,4 +184,10 @@ public void saveSimpleConfiguration() { public boolean hasBackgroundJobsRunning() { return false; } + + + @Override + public boolean backgroundJobsCompleteListener(PropertyChangeListener l) { + return false; + } } diff --git a/Report/src/org/sleuthkit/autopsy/report/report.java b/Report/src/org/sleuthkit/autopsy/report/report.java index 5dadd4722074f28e2dfa1533167b5e48f99f93da..ae8c5a2a571daa68186a87a95e685364e25099bb 100644 --- a/Report/src/org/sleuthkit/autopsy/report/report.java +++ b/Report/src/org/sleuthkit/autopsy/report/report.java @@ -5,16 +5,14 @@ package org.sleuthkit.autopsy.report; import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; -import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.SleuthkitCase; /** @@ -199,4 +197,57 @@ public HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> getHashHit() { return reportMap; } +@Override +public String getGroupedKeywordHit() { + StringBuilder table = new StringBuilder(); + HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> reportMap = new HashMap(); + Case currentCase = Case.getCurrentCase(); // get the most updated case + SleuthkitCase tempDb = currentCase.getSleuthkitCase(); + try + { + ResultSet uniqueresults = tempDb.runQuery("SELECT DISTINCT value_text from blackboard_attributes where attribute_type_id = '10' order by value_text ASC"); + while(uniqueresults.next()) + { + table.append("<strong>").append(uniqueresults.getString("value_text")).append("</strong>"); + table.append("<table><thead><tr><th>").append("File Name").append("</th><th>Preview</th><th>Keyword List</th></tr><tbody>"); + ArrayList<BlackboardArtifact> artlist = new ArrayList<BlackboardArtifact>(); + ResultSet tempresults = tempDb.runQuery("select DISTINCT artifact_id from blackboard_attributes where attribute_type_id = '10' and value_text = '" + uniqueresults.getString("value_text") +"'"); + while(tempresults.next()) + { + artlist.add(tempDb.getBlackboardArtifact(tempresults.getLong("artifact_id"))); + } + for(BlackboardArtifact art : artlist) + { + String filename = tempDb.getFsContentById(art.getObjectID()).getName(); + String preview = ""; + String set = ""; + table.append("<tr><td>").append(filename).append("</td>"); + ArrayList<BlackboardAttribute> tempatts = art.getAttributes(); + for(BlackboardAttribute att : tempatts) + { + if(att.getAttributeTypeID() == 12) + { + preview = "<td>" + att.getValueString() + "</td>"; + } + if(att.getAttributeTypeID() == 13) + { + set = "<td>" + att.getValueString() + "</td>"; + } + } + table.append(preview).append(set).append("</tr>"); + } + + + table.append("</tbody></table><br /><br />"); + } + } + catch (Exception e) + { + Logger.getLogger(report.class.getName()).log(Level.INFO, "Exception occurred", e); + } + + String result = table.toString(); + return result; +} + } \ No newline at end of file diff --git a/Report/src/org/sleuthkit/autopsy/report/reportFilter.form b/Report/src/org/sleuthkit/autopsy/report/reportFilter.form index dac82f751fd62a3ae232d6448074b04994c1e848..8c3a8123f96841b3533c168671a7ed19db352b9b 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportFilter.form +++ b/Report/src/org/sleuthkit/autopsy/report/reportFilter.form @@ -32,34 +32,35 @@ <DimensionLayout dim="0"> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" attributes="0"> + <EmptySpace min="-2" pref="38" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Group type="102" attributes="0"> - <EmptySpace min="-2" pref="28" max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jCheckBox3" alignment="0" min="-2" max="-2" attributes="0"/> <Group type="102" alignment="0" attributes="0"> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jCheckBox2" alignment="0" min="-2" max="-2" attributes="0"/> <Component id="jCheckBox1" alignment="0" min="-2" max="-2" attributes="0"/> - <Component id="cancelButton" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> <Group type="103" groupAlignment="0" attributes="0"> <Component id="jCheckBox5" min="-2" max="-2" attributes="0"/> - <Group type="103" alignment="0" groupAlignment="0" attributes="0"> - <Component id="jCheckBox4" min="-2" max="-2" attributes="0"/> - <Component id="progBar" alignment="1" min="-2" pref="188" max="-2" attributes="0"/> - </Group> + <Component id="jCheckBox4" alignment="0" min="-2" max="-2" attributes="0"/> </Group> </Group> </Group> + <EmptySpace min="-2" pref="69" max="-2" attributes="0"/> </Group> <Group type="102" alignment="0" attributes="0"> - <EmptySpace min="-2" pref="106" max="-2" attributes="0"/> <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="15" max="32767" attributes="0"/> + <Component id="cancelButton" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="progBar" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="42" max="-2" attributes="0"/> </Group> </Group> - <EmptySpace pref="108" max="32767" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> </Group> </Group> </DimensionLayout> @@ -79,13 +80,12 @@ <EmptySpace type="separate" max="-2" attributes="0"/> <Component id="jCheckBox3" min="-2" max="-2" attributes="0"/> <EmptySpace type="separate" max="-2" attributes="0"/> - <Group type="103" groupAlignment="1" attributes="0"> - <Group type="102" attributes="0"> - <Component id="jButton1" min="-2" max="-2" attributes="0"/> - <EmptySpace type="unrelated" max="-2" attributes="0"/> - <Component id="progBar" pref="25" max="32767" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="progBar" pref="23" max="32767" attributes="1"/> + <Group type="103" alignment="0" groupAlignment="3" attributes="0"> + <Component id="jButton1" alignment="3" max="32767" attributes="1"/> + <Component id="cancelButton" alignment="3" max="32767" attributes="1"/> </Group> - <Component id="cancelButton" min="-2" max="-2" attributes="0"/> </Group> <EmptySpace max="-2" attributes="0"/> </Group> diff --git a/Report/src/org/sleuthkit/autopsy/report/reportFilter.java b/Report/src/org/sleuthkit/autopsy/report/reportFilter.java index 2ecee61ef0ac45db7a92b31cf311daf1dbeeb6d1..f3404291f03e8e401ceab46d47d1914264f63117 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportFilter.java +++ b/Report/src/org/sleuthkit/autopsy/report/reportFilter.java @@ -106,26 +106,28 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() + .addGap(38, 38, 38) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGap(28, 28, 28) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jCheckBox3) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jCheckBox2) - .addComponent(jCheckBox1) - .addComponent(cancelButton)) + .addComponent(jCheckBox1)) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jCheckBox5) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jCheckBox4) - .addComponent(progBar, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 188, javax.swing.GroupLayout.PREFERRED_SIZE)))))) + .addComponent(jCheckBox4)))) + .addGap(69, 69, 69)) .addGroup(layout.createSequentialGroup() - .addGap(106, 106, 106) - .addComponent(jButton1))) - .addContainerGap(108, Short.MAX_VALUE)) + .addComponent(jButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 15, Short.MAX_VALUE) + .addComponent(cancelButton) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(progBar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(42, 42, 42))) + .addContainerGap()) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -141,12 +143,11 @@ public void actionPerformed(java.awt.event.ActionEvent evt) { .addGap(18, 18, 18) .addComponent(jCheckBox3) .addGap(18, 18, 18) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) - .addGroup(layout.createSequentialGroup() - .addComponent(jButton1) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(progBar, javax.swing.GroupLayout.DEFAULT_SIZE, 25, Short.MAX_VALUE)) - .addComponent(cancelButton)) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(progBar, javax.swing.GroupLayout.DEFAULT_SIZE, 23, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jButton1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(cancelButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) .addContainerGap()) ); }// </editor-fold>//GEN-END:initComponents diff --git a/Report/src/org/sleuthkit/autopsy/report/reportHTML.java b/Report/src/org/sleuthkit/autopsy/report/reportHTML.java index 4c764d06e0b873f3af05a066f1f8e0e31eb92a9a..350ac7300d5d376c4739f0617f20000d1b6d237f 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportHTML.java +++ b/Report/src/org/sleuthkit/autopsy/report/reportHTML.java @@ -5,7 +5,6 @@ package org.sleuthkit.autopsy.report; import java.io.BufferedWriter; -import java.io.File; import java.io.FileWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -13,13 +12,16 @@ import java.util.Date; import java.util.HashMap; import java.util.Map.Entry; +import java.util.TreeMap; import java.util.logging.Level; import java.util.logging.Logger; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskData; /** * @@ -31,16 +33,65 @@ public class reportHTML { public static StringBuilder formatted_Report = new StringBuilder(); public static String htmlPath = ""; public reportHTML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> report, reportFilter rr){ - + + //This is literally a terrible way to count up all the types of artifacts, and doesn't include any added ones. + //Unlike the XML report, which is dynamic, this is formatted and needs to be redone later instead of being hardcoded. + + int countGen = 0; + int countWebBookmark = 0; + int countWebCookie = 0; + int countWebHistory = 0; + int countWebDownload = 0; + int countRecentObjects = 0; + int countTrackPoint = 0; + int countInstalled = 0; + int countKeyword = 0; + int countHash = 0; + for (Entry<BlackboardArtifact,ArrayList<BlackboardAttribute>> entry : report.entrySet()) { + if(entry.getKey().getArtifactTypeID() == 1){ + countGen++; + } + if(entry.getKey().getArtifactTypeID() == 2){ + countWebBookmark++; + } + if(entry.getKey().getArtifactTypeID() == 3){ + + countWebCookie++; + } + if(entry.getKey().getArtifactTypeID() == 4){ + + countWebHistory++; + } + if(entry.getKey().getArtifactTypeID() == 5){ + countWebDownload++; + } + if(entry.getKey().getArtifactTypeID() == 6){ + countRecentObjects++; + } + if(entry.getKey().getArtifactTypeID() == 7){ + countTrackPoint++; + } + if(entry.getKey().getArtifactTypeID() == 8){ + countInstalled++; + } + if(entry.getKey().getArtifactTypeID() == 9){ + countKeyword++; + } + if(entry.getKey().getArtifactTypeID() == 10){ + countHash++; + } + } try{ + + String ingestwarning = "<h2 style=\"color: red;\">Warning, this report was run before ingest services completed!</h2>"; Case currentCase = Case.getCurrentCase(); // get the most updated case SleuthkitCase skCase = currentCase.getSleuthkitCase(); String caseName = currentCase.getName(); - String rrpath = System.getProperty("user.dir"); - rrpath = rrpath.substring(0, rrpath.length()-14); - rrpath = rrpath + "autopsy\\thirdparty\\"; Integer imagecount = currentCase.getImageIDs().length; + Integer totalfiles = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG); + Integer totaldirs = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR); + int reportsize = report.size(); Integer filesystemcount = currentCase.getRootObjectsCount(); DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy"); @@ -68,20 +119,27 @@ public reportHTML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> re // Add summary information now formatted_Report.append("<h1>Report for Case: ").append(caseName).append("</h1>"); + if(IngestManager.getDefault().isIngestRunning()) + { + formatted_Report.append(ingestwarning); + } formatted_Report.append("<h2>Case Summary</h2><p>HTML Report Generated by <strong>Autopsy 3</strong> on ").append(datetime).append("<br /><ul>"); formatted_Report.append("<li># of Images: ").append(imagecount).append("</li>"); formatted_Report.append("<li>FileSystems: ").append(filesystemcount).append("</li>"); - String tableHeader = "<table><thead><tr><th>Artifact ID</th><th>Name</th><th>Size</th><th>Attribute</th><th>Value</th></tr></thead><tbody>"; - StringBuilder nodeGen = new StringBuilder("<h3>General Information</h3>" + tableHeader); - StringBuilder nodeWebBookmark = new StringBuilder("<h3>Web Bookmarks</h3>" + tableHeader); - StringBuilder nodeWebCookie = new StringBuilder("<h3>Web Cookies</h3>" + tableHeader); - StringBuilder nodeWebHistory = new StringBuilder("<h3>Web History</h3>" + tableHeader); - StringBuilder nodeWebDownload = new StringBuilder("<h3>Web Downloads</h3>" + tableHeader); - StringBuilder nodeRecentObjects = new StringBuilder("<h3>Recent Documents</h3>" + tableHeader); - StringBuilder nodeTrackPoint = new StringBuilder("<h3>Track Points</h3>" + tableHeader); - StringBuilder nodeInstalled = new StringBuilder("<h3>Installed Programs</h3>" + tableHeader); - StringBuilder nodeKeyword = new StringBuilder("<h3>Keyword Search Hits</h3>" + tableHeader); - StringBuilder nodeHash = new StringBuilder("<h3>Hashset Hits</h3>" + tableHeader); + formatted_Report.append("<li># of Files: ").append(totalfiles.toString()).append("</li>"); + formatted_Report.append("<li># of Dirs: ").append(totaldirs.toString()).append("</li>"); + formatted_Report.append("<li># of Artifacts: ").append(reportsize).append("</li>"); + String tableHeader = "<table><thead><tr>"; + StringBuilder nodeGen = new StringBuilder("<h3>General Information (").append(countGen).append(")</h3>").append(tableHeader).append("<th>Attribute</th><th>Value</th></tr></thead><tbody>"); + StringBuilder nodeWebBookmark = new StringBuilder("<h3>Web Bookmarks (").append(countWebBookmark).append(")</h3>").append(tableHeader).append("<th>URL</th><th>Title</th><th>Program</th></tr></thead><tbody>"); + StringBuilder nodeWebCookie = new StringBuilder("<h3>Web Cookies (").append(countWebCookie).append(")</h3>").append(tableHeader).append("<th>URL</th><th>Date</th><th>Name</th><th>Value</th><th>Program</th></tr></thead><tbody>"); + StringBuilder nodeWebHistory = new StringBuilder("<h3>Web History (").append(countWebHistory).append(")</h3>").append(tableHeader).append("<th>URL</th><th>Date</th><th>Referrer</th><th>Title</th><th>Program</th></tr></thead><tbody>"); + StringBuilder nodeWebDownload = new StringBuilder("<h3>Web Downloads (").append(countWebDownload).append(")</h3>").append(tableHeader).append("<th>File</th><th>Source</th><th>Time</th><th>Program</th></tr></thead><tbody>"); + StringBuilder nodeRecentObjects = new StringBuilder("<h3>Recent Documents (").append(countRecentObjects).append(")</h3>").append(tableHeader).append("<th>Artifact ID</th><th>Name</th><th>Size</th><th>Name</th><th>Path</th></tr></thead><tbody>"); + StringBuilder nodeTrackPoint = new StringBuilder("<h3>Track Points (").append(countTrackPoint).append(")</h3>").append(tableHeader).append("<th>Artifact ID</th><th>Name</th><th>Size</th><th>Attribute</th><th>Value</th></tr></thead><tbody>"); + StringBuilder nodeInstalled = new StringBuilder("<h3>Installed Programs (").append(countInstalled).append(")</h3>").append(tableHeader).append("<th>Artifact ID</th><th>Name</th><th>Size</th><th>Attribute</th><th>Value</th></tr></thead><tbody>"); + StringBuilder nodeKeyword = new StringBuilder("<h3>Keyword Search Hits (").append(countKeyword).append(")</h3>"); + StringBuilder nodeHash = new StringBuilder("<h3>Hashset Hits (").append(countHash).append(")</h3>").append(tableHeader).append("<th>Artifact ID</th><th>Name</th><th>Size</th><th>Hashset Name</th></tr></thead><tbody>"); for (Entry<BlackboardArtifact,ArrayList<BlackboardAttribute>> entry : report.entrySet()) { if(reportFilter.cancel == true){ @@ -95,64 +153,103 @@ public reportHTML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> re Long filesize = file.getSize(); - - - // Get all the attributes for this guy + + TreeMap<Integer, String> attributes = new TreeMap<Integer,String>(); + // Get all the attributes, line them up to be added. for (BlackboardAttribute tempatt : entry.getValue()) { - if(reportFilter.cancel == true){ + if(reportFilter.cancel == true){ break; } - artifact.append("<tr><td>").append(objId.toString()); - artifact.append("</td><td><strong>").append(file.getName().toString()).append("</strong></td>"); - //artifact.append("Path: ").append(file.getParentPath()); - artifact.append("<td>").append(filesize.toString()).append("</td>"); - StringBuilder attribute = new StringBuilder("<td>").append(tempatt.getAttributeTypeDisplayName()).append("</td>"); - attribute.append("<td>").append(tempatt.getValueString()).append("</td></tr>"); - //attribute.append("<li style=\"list-style-type: none;\"> Context: ").append(tempatt.getContext()).append("</li>"); - artifact.append(attribute); + int type = tempatt.getAttributeTypeID(); + String value = tempatt.getValueString(); + attributes.put(type, value); cc++; } - //artifact.append("</tr>"); + + if(entry.getKey().getArtifactTypeID() == 1){ + + artifact.append("</tr>"); nodeGen.append(artifact); } if(entry.getKey().getArtifactTypeID() == 2){ + artifact.append("<tr><td>").append(attributes.get(1)).append("</td>"); + artifact.append("<td>").append(attributes.get(3)).append("</td>"); + artifact.append("<td>").append(attributes.get(4)).append("</td>"); + artifact.append("</tr>"); nodeWebBookmark.append(artifact); } if(entry.getKey().getArtifactTypeID() == 3){ - + artifact.append("<tr><td>").append(attributes.get(1)).append("</td>"); + artifact.append("<td>").append(attributes.get(2)).append("</td>"); + artifact.append("<td>").append(attributes.get(3)).append("</td>"); + artifact.append("<td>").append(attributes.get(6)).append("</td>"); + artifact.append("<td>").append(attributes.get(4)).append("</td>"); + artifact.append("</tr>"); nodeWebCookie.append(artifact); } if(entry.getKey().getArtifactTypeID() == 4){ - + artifact.append("<tr><td>").append(attributes.get(1)).append("</td>"); + artifact.append("<td>").append(attributes.get(2)).append("</td>"); + artifact.append("<td>").append(attributes.get(32)).append("</td>"); + artifact.append("<td>").append(attributes.get(3)).append("</td>"); + artifact.append("<td>").append(attributes.get(4)).append("</td>"); + artifact.append("</tr>"); nodeWebHistory.append(artifact); } if(entry.getKey().getArtifactTypeID() == 5){ + artifact.append("<tr><td>").append(attributes.get(8)).append("</td>"); + artifact.append("<td>").append(attributes.get(1)).append("</td>"); + artifact.append("<td>").append(attributes.get(2)).append("</td>"); + artifact.append("<td>").append(attributes.get(4)).append("</td>"); + artifact.append("</tr>"); nodeWebDownload.append(artifact); } if(entry.getKey().getArtifactTypeID() == 6){ + artifact.append("<tr><td>").append(objId.toString()); + artifact.append("</td><td><strong>").append(file.getName().toString()).append("</strong></td>"); + artifact.append("<td>").append(filesize.toString()).append("</td>"); + artifact.append("</tr>"); nodeRecentObjects.append(artifact); } if(entry.getKey().getArtifactTypeID() == 7){ + artifact.append("<tr><td>").append(objId.toString()); + artifact.append("</td><td><strong>").append(file.getName().toString()).append("</strong></td>"); + artifact.append("<td>").append(filesize.toString()).append("</td>"); + artifact.append("</tr>"); nodeTrackPoint.append(artifact); } if(entry.getKey().getArtifactTypeID() == 8){ + artifact.append("<tr><td>").append(objId.toString()); + artifact.append("</td><td><strong>").append(file.getName().toString()).append("</strong></td>"); + artifact.append("<td>").append(filesize.toString()).append("</td>"); + artifact.append("</tr>"); nodeInstalled.append(artifact); } if(entry.getKey().getArtifactTypeID() == 9){ - nodeKeyword.append(artifact); + + // artifact.append("<table><thead><tr><th>Artifact ID</th><th>Name</th><th>Size</th>"); + + // artifact.append("</tr></table>"); + // nodeKeyword.append(artifact); } if(entry.getKey().getArtifactTypeID() == 10){ + artifact.append("<tr><td>").append(objId.toString()); + artifact.append("</td><td><strong>").append(file.getName().toString()).append("</strong></td>"); + artifact.append("<td>").append(filesize.toString()).append("</td>"); + //artifact.append("<td>").append(attributes.get(31)).append("</td>"); + artifact.append("<td>").append(attributes.get(30)).append("</td>"); + artifact.append("</tr>"); nodeHash.append(artifact); } cc++; rr.progBarSet(cc); } //Add them back in order - formatted_Report.append(nodeGen); - formatted_Report.append("</tbody></table>"); + //formatted_Report.append(nodeGen); + // formatted_Report.append("</tbody></table>"); formatted_Report.append(nodeWebBookmark); formatted_Report.append("</tbody></table>"); formatted_Report.append(nodeWebCookie); @@ -163,19 +260,25 @@ public reportHTML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> re formatted_Report.append("</tbody></table>"); formatted_Report.append(nodeRecentObjects); formatted_Report.append("</tbody></table>"); - formatted_Report.append(nodeTrackPoint); - formatted_Report.append("</tbody></table>"); + // formatted_Report.append(nodeTrackPoint); + //formatted_Report.append("</tbody></table>"); formatted_Report.append(nodeInstalled); - formatted_Report.append("</tbody></table>"); + formatted_Report.append("</tbody></table>"); formatted_Report.append(nodeKeyword); - formatted_Report.append("</tbody></table>"); + if(countKeyword > 0){ + report keywords = new report(); + formatted_Report.append(keywords.getGroupedKeywordHit()); + // "<table><thead><tr><th>Artifact ID</th><th>Name</th><th>Size</th> + // formatted_Report.append("</tbody></table>"); + } + formatted_Report.append(nodeHash); formatted_Report.append("</tbody></table>"); //end of master loop formatted_Report.append("</div></div></body></html>"); - htmlPath = currentCase.getCaseDirectory()+"/Temp/" + caseName + "-" + datenotime + ".html"; + htmlPath = currentCase.getCaseDirectory()+"/Reports/" + caseName + "-" + datenotime + ".html"; BufferedWriter out = new BufferedWriter(new FileWriter(htmlPath)); out.write(formatted_Report.toString()); diff --git a/Report/src/org/sleuthkit/autopsy/report/reportInterface.java b/Report/src/org/sleuthkit/autopsy/report/reportInterface.java index d94b62e943f36000be37a9db6551b4e136f38ad3..ba8f3ef6f117d81b0d88a929ce91980f5c68ea11 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportInterface.java +++ b/Report/src/org/sleuthkit/autopsy/report/reportInterface.java @@ -22,4 +22,5 @@ public interface reportInterface{ public HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> getRecentObject(); public HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> getHashHit(); public HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> getKeywordHit(); + public String getGroupedKeywordHit(); } diff --git a/Report/src/org/sleuthkit/autopsy/report/reportPanel.form b/Report/src/org/sleuthkit/autopsy/report/reportPanel.form index 2f20df384e97caba177bf860dfc628503046de2d..39a8765e768ae30f9903db87e5081531b2d552c1 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportPanel.form +++ b/Report/src/org/sleuthkit/autopsy/report/reportPanel.form @@ -7,6 +7,9 @@ <Component class="javax.swing.JOptionPane" name="jOptionPane1"> </Component> </NonVisualComponents> + <Properties> + <Property name="focusTraversalPolicyProvider" type="boolean" value="true"/> + </Properties> <AccessibilityProperties> <Property name="AccessibleContext.accessibleName" type="java.lang.String" value=""/> <Property name="AccessibleContext.accessibleParent" type="javax.accessibility.Accessible" editor="org.netbeans.modules.form.RADVisualComponent$AccessibleParentEditor"> diff --git a/Report/src/org/sleuthkit/autopsy/report/reportPanel.java b/Report/src/org/sleuthkit/autopsy/report/reportPanel.java index c32603aa97c1978127298497f0a92099cc728771..c03e38ccfe4fc2d5f67d9bfa6b911d1818381764 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportPanel.java +++ b/Report/src/org/sleuthkit/autopsy/report/reportPanel.java @@ -10,9 +10,11 @@ */ package org.sleuthkit.autopsy.report; import java.awt.event.ActionListener; +import java.io.BufferedWriter; import java.io.FileOutputStream; +import java.io.FileWriter; import java.io.IOException; -import javax.swing.filechooser.FileFilter; +import org.jdom.output.XMLOutputter; /** * @@ -42,6 +44,8 @@ private void initComponents() { jButton1 = new javax.swing.JButton(); saveReport = new javax.swing.JButton(); + setFocusTraversalPolicyProvider(true); + jEditorPane1.setContentType(org.openide.util.NbBundle.getMessage(reportPanel.class, "reportPanel.jEditorPane1.contentType")); // NOI18N jEditorPane1.setEditable(false); jScrollPane1.setViewportView(jEditorPane1); @@ -121,13 +125,19 @@ private void saveReportAction(){ private void exportReport(String path){ - path = reportUtils.changeExtension(path, ".html"); + String htmlpath = reportUtils.changeExtension(path, ".html"); + String xmlpath = reportUtils.changeExtension(path, ".xml"); try { - FileOutputStream out = new FileOutputStream(path); + FileOutputStream out = new FileOutputStream(htmlpath); out.write(reportHTML.formatted_Report.toString().getBytes()); out.flush(); out.close(); + FileOutputStream xmlout = new FileOutputStream(xmlpath); + XMLOutputter serializer = new XMLOutputter(); + serializer.output(reportXML.xmldoc, xmlout); + xmlout.flush(); + xmlout.close(); jOptionPane1.showMessageDialog(this, "Report has been successfully saved!"); } catch (IOException e) { diff --git a/Report/src/org/sleuthkit/autopsy/report/reportPanelAction.java b/Report/src/org/sleuthkit/autopsy/report/reportPanelAction.java index a329131c0a4c381381b67d801cca393e26f98cc7..9d3dc3f8c537071d325b6b0f2ec6c4a76cc42c72 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportPanelAction.java +++ b/Report/src/org/sleuthkit/autopsy/report/reportPanelAction.java @@ -97,7 +97,7 @@ public void actionPerformed(ActionEvent e) { // add the panel to the popup window popUpWindow.add(panel); popUpWindow.pack(); - popUpWindow.setResizable(false); + popUpWindow.setResizable(true); // set the location of the popUp Window on the center of the screen Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize(); @@ -107,7 +107,7 @@ public void actionPerformed(ActionEvent e) { popUpWindow.setVisible(true); rr.progBarDone(); - // add the command to close the window to the button on the Case Properties form / panel + } } catch (Exception ex) { Log.get(reportFilterAction.class).log(Level.WARNING, "Error displaying " + ACTION_NAME + " window.", ex); diff --git a/Report/src/org/sleuthkit/autopsy/report/reportXML.java b/Report/src/org/sleuthkit/autopsy/report/reportXML.java index 87aeacb691ec28de3c5e376f6b1d4e16a0ca1a2e..6a25b35ba8a0a0887725420b41de883f95883649 100644 --- a/Report/src/org/sleuthkit/autopsy/report/reportXML.java +++ b/Report/src/org/sleuthkit/autopsy/report/reportXML.java @@ -19,6 +19,7 @@ import org.jdom.Element; import org.jdom.output.XMLOutputter; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.Content; @@ -27,8 +28,9 @@ import org.sleuthkit.datamodel.File; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskData; public class reportXML { - + public static Document xmldoc = new Document(); public reportXML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> report, reportFilter rr){ try{ Case currentCase = Case.getCurrentCase(); // get the most updated case @@ -36,8 +38,10 @@ public reportXML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> rep String caseName = currentCase.getName(); Integer imagecount = currentCase.getImageIDs().length; Integer filesystemcount = currentCase.getRootObjectsCount(); + Integer totalfiles = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG); + Integer totaldirs = skCase.countFsContentType(TskData.TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR); Element root = new Element("Case"); - Document xmldoc = new Document(root); + xmldoc = new Document(root); DateFormat datetimeFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss"); DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); @@ -47,9 +51,15 @@ public reportXML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> rep root.addContent(comment); //Create summary node involving how many of each type Element summary = new Element("Summary"); + if(IngestManager.getDefault().isIngestRunning()) + { + summary.addContent(new Element("Warning").setText("Report was run before ingest services completed!")); + } summary.addContent(new Element("Name").setText(caseName)); summary.addContent(new Element("Total-Images").setText(imagecount.toString())); summary.addContent(new Element("Total-FileSystems").setText(filesystemcount.toString())); + summary.addContent(new Element("Total-Files").setText(totalfiles.toString())); + summary.addContent(new Element("Total-Directories").setText(totaldirs.toString())); root.addContent(summary); //generate the nodes for each of the types so we can use them later Element nodeGen = new Element("General-Information"); @@ -145,7 +155,7 @@ public reportXML (HashMap<BlackboardArtifact,ArrayList<BlackboardAttribute>> rep root.addContent(nodeHash); try { - FileOutputStream out = new FileOutputStream(currentCase.getCaseDirectory()+"/Temp/" + caseName + "-" + datenotime + ".xml"); + FileOutputStream out = new FileOutputStream(currentCase.getCaseDirectory()+"/Reports/" + caseName + "-" + datenotime + ".xml"); XMLOutputter serializer = new XMLOutputter(); serializer.output(xmldoc, out); out.flush();