diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageLoadingPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageLoadingPanel.java index f201c80814..6b89366343 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageLoadingPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageLoadingPanel.java @@ -105,10 +105,10 @@ public class AddImageLoadingPanel extends javax.swing.JPanel { void setErrors(final String errors, boolean critical) { crDbProgressBar.setValue(100); //always invoked when process completed if (critical) { - progressLabel.setText("*Failed to add image (critical errors encountered). Click below to view the Add Image Log."); + progressLabel.setText("*Failed to add image (critical errors encountered). Click below to view the log."); } else { - progressLabel.setText("*Image added (non-critical image errors encountered). Click below to view the Add Image Log."); + progressLabel.setText("*Data Source added (non-critical errors encountered). Click below to view the log."); } errorButton = new JButton(); errorButton.setText("View Log"); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form index 88c36cd4c3..1042b934b3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.form @@ -103,6 +103,9 @@ + + + @@ -200,6 +203,9 @@ + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java index b1fa10a603..4aa6de6740 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel1.java @@ -57,7 +57,7 @@ final class AddImageVisualPanel1 extends JPanel { private AddImageWizardPanel1 wizPanel; private ContentTypeModel model; - ContentTypePanel currentPanel; + private ContentTypePanel currentPanel; /** * Creates new form AddImageVisualPanel1 @@ -231,13 +231,13 @@ final class AddImageVisualPanel1 extends JPanel { jLabel2 = new javax.swing.JLabel(); nextLabel = new javax.swing.JLabel(); timeZoneLabel = new javax.swing.JLabel(); - timeZoneComboBox = new javax.swing.JComboBox(); + timeZoneComboBox = new javax.swing.JComboBox(); noFatOrphansCheckbox = new javax.swing.JCheckBox(); descLabel = new javax.swing.JLabel(); inputPanel = new javax.swing.JPanel(); typeTabel = new javax.swing.JLabel(); typePanel = new javax.swing.JPanel(); - typeComboBox = new javax.swing.JComboBox(); + typeComboBox = new javax.swing.JComboBox(); imgInfoLabel = new javax.swing.JLabel(); org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(AddImageVisualPanel1.class, "AddImageVisualPanel1.jLabel2.text")); // NOI18N @@ -355,9 +355,9 @@ final class AddImageVisualPanel1 extends JPanel { private javax.swing.JLabel jLabel2; private javax.swing.JLabel nextLabel; private javax.swing.JCheckBox noFatOrphansCheckbox; - private javax.swing.JComboBox timeZoneComboBox; + private javax.swing.JComboBox timeZoneComboBox; private javax.swing.JLabel timeZoneLabel; - private javax.swing.JComboBox typeComboBox; + private javax.swing.JComboBox typeComboBox; private javax.swing.JPanel typePanel; private javax.swing.JLabel typeTabel; // End of variables declaration//GEN-END:variables @@ -377,9 +377,10 @@ final class AddImageVisualPanel1 extends JPanel { /** * ComboBoxModel to control typeComboBox and supply ImageTypePanels. */ - private class ContentTypeModel implements ComboBoxModel { - ContentTypePanel selected; - ContentTypePanel[] types = ContentTypePanel.getPanels(); + private class ContentTypeModel implements ComboBoxModel { + private ContentTypePanel selected; + private ContentTypePanel[] types = ContentTypePanel.getPanels(); + @Override public void setSelectedItem(Object anItem) { @@ -398,7 +399,7 @@ final class AddImageVisualPanel1 extends JPanel { } @Override - public Object getElementAt(int index) { + public ContentTypePanel getElementAt(int index) { return types[index]; } diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java index 63d5514303..678b1700d3 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageVisualPanel3.java @@ -23,7 +23,7 @@ import java.awt.BorderLayout; import javax.swing.JPanel; /** - * Image added, ingest configure wizard visual panel 3 + * Data Source added, ingest configure wizard visual panel 3 */ public class AddImageVisualPanel3 extends javax.swing.JPanel { private JPanel ingestPanel = null; diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java index dbe05d2650..dcd58dd201 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel2.java @@ -29,7 +29,7 @@ import org.openide.util.HelpCtx; import org.openide.util.Lookup; /** - * The "Add Image" wizard panel2. Handles processing the image in a worker + * The "Add Data Source" wizard panel2. Handles processing the image in a worker * thread, and any errors that may occur during the add process. */ class AddImageWizardPanel2 implements WizardDescriptor.Panel { @@ -90,7 +90,7 @@ class AddImageWizardPanel2 implements WizardDescriptor.Panel { */ void setStateStarted() { component.getCrDbProgressBar().setIndeterminate(true); - component.changeProgressBarTextAndColor("*Adding the image may take some time for large images.", 0, Color.black); + component.changeProgressBarTextAndColor("*This process take some time for large data sources.", 0, Color.black); } /** diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java index e3b944ce6b..7292309379 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/AddImageWizardPanel3.java @@ -570,7 +570,7 @@ class AddImageWizardPanel3 implements WizardDescriptor.Panel { cleanupImage.enable(); if (errorString == null) { // complete progress bar - wizPanel.getComponent().changeProgressBarTextAndColor("*Image added.", 100, Color.black); + wizPanel.getComponent().changeProgressBarTextAndColor("*Data Source added.", 100, Color.black); } // Get attention for the process finish diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties index cef89dc144..487f0aba18 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Bundle.properties @@ -94,9 +94,6 @@ NewJPanel.jFormattedTextField1.text=jFormattedTextField1 NewJPanel.jButton1.text=Rename NewJPanel.jLabel4.text=Database: AddImageVisualPanel2.indexImageCheckBox.text=Index image for keyword search -AddImageVisualPanel4.jLabel1.text=Image was successfully added to the case and is being processed. -AddImageVisualPanel4.crDbLabel.text=Image Added and Being Processed -AddImageVisualPanel4.addImgButton.text=Add Another Image AddImageVisualPanel3.titleLabel.text=Configure Ingest Modules AddImageVisualPanel3.subtitleLabel.text=Configure the ingest modules you would like to run on this data source. CasePropertiesForm.caseNumberLabel.text=Case Number: @@ -132,12 +129,12 @@ MissingImageDialog.cancelButton.text=Cancel LocalDiskPanel.errorLabel.text=Error Label AddImageVisualPanel1.typeTabel.text=Select source type to add: AddImageVisualPanel1.imgInfoLabel.text=Enter Data Source Information: -AddImageLoadingPanel.crDbLabel.text=Adding Image +AddImageLoadingPanel.crDbLabel.text=Adding Data Source AddImageLoadingPanel.Label_CurrentDirectory_Static.text=Currently Processing: -AddImageLoadingPanel.jLabel5.text=Processing Image and Adding to Database +AddImageLoadingPanel.jLabel5.text=Processing Data Source and Adding to Database AddImageLoadingPanel.jLabel1.text=File system information is being added to a local database. File analysis will start when this finishes. AddImageDonePanel.statusLabel.text=File system has been added to the local database. Files are being analyzed. -AddImageDonePanel.crDbLabel.text=Adding Image - Complete +AddImageDonePanel.crDbLabel.text=Adding Data Source - Complete LocalFilesPanel.infoLabel.text=Add local files and folders: LocalFilesPanel.selectButton.text=Add LocalFilesPanel.localFileChooser.dialogTitle=Select Local Files or Folders diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java index 4b8e20064a..0331635a9d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CasePropertiesAction.java @@ -75,7 +75,7 @@ public final class CasePropertiesAction extends CallableSystemAction { int totalImage = currentCase.getRootObjectsCount(); // put the image paths information into hashmap - Map imgPaths = currentCase.getImagePaths(currentCase.getSleuthkitCase()); + Map imgPaths = Case.getImagePaths(currentCase.getSleuthkitCase()); // create the case properties form CasePropertiesForm cpf = new CasePropertiesForm(currentCase, crDate, caseDir, imgPaths); diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard1_Help.png b/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard1_Help.png index ce2842f348..b8afc7d9a3 100644 Binary files a/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard1_Help.png and b/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard1_Help.png differ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard2_Help.png b/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard2_Help.png index a2ee481917..999b5b3cf4 100644 Binary files a/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard2_Help.png and b/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard2_Help.png differ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard3_Help.png b/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard3_Help.png index f292c9a3f6..59afc70a20 100644 Binary files a/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard3_Help.png and b/Core/src/org/sleuthkit/autopsy/casemodule/docs/AddImageWizard3_Help.png differ diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/aboutImage.html b/Core/src/org/sleuthkit/autopsy/casemodule/docs/aboutImage.html index 3898691109..72ed8113a0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/docs/aboutImage.html +++ b/Core/src/org/sleuthkit/autopsy/casemodule/docs/aboutImage.html @@ -1,35 +1,51 @@ - Disk Image Basics + Data Source Basics -

About Disk Images

+

About Data Sources

+

- In Autopsy, an "image" refers to a byte-for-byte copy of a hard drive or other storage media. - To analyze an image, you must use the Add Image Wizard + Autopsy supports 3 types of data sources that can be added to the Case:

+
    +
  • Disk Image (raw, Encase, etc). + "Image" refers to a byte-for-byte copy of a hard drive or other storage media. +
  • +
  • Disk Device (physical or logical disk partition, plugged in the user machine and detected by Autopsy). + Note: to correctly detect all devices, Autopsy needs to run as Administrator. +
  • +
  • Logical Files (files and folders on the user machine file system)
  • +
+ +

+ User needs to select the data source type from the pull down menu in the Add Data Source wizard. +

+ +

+ To analyze a Data Source, user should use the Add Data Source Wizard to add it to a case.

- Autopsy populates an embedded database for each image that it imports. - This database is a SQLite database and it contains all of the file system metadata from the image. - The database is stored in the case directory, but the image will stay in its original location. - The image must remain accessible for the duration of the analysis because the database contains only basic file system information. - The image is needed to retrieve file content. + Autopsy populates an embedded database for each data source (image, disk device, logical files) that it imports. + This database is a SQLite database and it contains all of the file system metadata from the input data source. + The database is stored in the case directory, but the data source will stay in its original location. + The data source must remain accessible for the duration of the analysis because the database contains only basic file system information (meta-data, not the actual content). + The image / files are needed to retrieve file content.

-

Supported Formats

+

Supported Image Formats

Currently, Autopsy supports these image formats:

    -
  • Raw Single (For example: *.img, *.dd, etc)
  • +
  • Raw Single (For example: *.img, *.dd, *.raw, etc)
  • Raw Split (For example: *.001, *.002, *.aa, *.ab, etc)
  • EnCase (For example: *.e01, *e02, etc)
-

Removing an Image

-

You cannot currently remove an image from a case.

+

Removing a Data Source

+

You cannot currently remove an data source from a case.

diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/addImage.html b/Core/src/org/sleuthkit/autopsy/casemodule/docs/addImage.html index 6d5bbe3f37..33ec0a3a57 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/docs/addImage.html +++ b/Core/src/org/sleuthkit/autopsy/casemodule/docs/addImage.html @@ -1,23 +1,27 @@ - Adding Image Wizard + Adding Data Source (Image, Disk, Files) Wizard -

Adding An Image

-

There are two ways to add an image to the currently opened case:

+

Adding a Data Source

+ +

There are two ways to add an data source to the currently opened case:

    -
  • Go to "File" and select "Add Image..."
  • +
  • Go to "File" and select "Add Data Source..."
  • Select the Add Image Icon icon on the toolbar
-

This will bring up the Add Image wizard. It will guide you through the process.

+

This will bring up the Add Data Source wizard. It will guide you through the process.

Here are some notes on what is going on during the process:

  • - The first panel will ask you to browse for the image on your machine. - You will also need to specify the timezone that the disk image came from so that the dates and times can be properly displayed and converted. + The first panel will ask you to select the data source type and + browse for the data source (image or files located on the computer, or select the device detected). + + In case of adding a disk image, you will also need to specify the timezone that the disk image came from + so that the dates and times can be properly displayed and converted. As soon as you click 'Next >', Autopsy will begin analyzing the disk image and populating the database in the background.
    Add Image Wizard Panel 1 Help @@ -29,21 +33,21 @@ Add Image Wizard Panel 3 Help
  • - The third panel provides a progress bar and information about the image Autopsy is currently processing. - If small enough, the image may have already finished processing, allowing you to continue past this panel. + The third panel provides a progress bar and information about the data source Autopsy is currently processing. + If small enough, the input may have already finished processing, allowing you to continue past this panel. However, it may be necessary to wait for a short time while the database is populated.
    Add Image Wizard Panel 2 Help
  • - Once the image finishes adding, the ingest modules you selected will automatically run in the background. - If the image is processed before you select ingest modules, Autopsy will wait until you have done so. + Once the input data source finishes adding, the ingest modules you selected will automatically run in the background. + If the data source is processed before you select ingest modules, Autopsy will wait until you have done so.
-

+

- Note that Autopsy will store the path to the image in its configuration file. - If the image moves, then Autopsy will give an error because it can't find the image file. + Note that in case of image, Autopsy will store the path to the image in its configuration file. + If the image moves, then Autopsy will give an error because it can't find the image file and it will prompt user to point to the new image location.

\ No newline at end of file diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-about.html b/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-about.html index b7dcf30dae..df21b69f50 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-about.html +++ b/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-about.html @@ -8,8 +8,8 @@

About Cases

- In Autopsy, a "case" is a container concept for a set of images. - The set of images could be from multiple drives in a single computer or from multiple computers. + In Autopsy, a "case" is a container concept for a set of input data sources (disk images, disk devices, logical files). + The set of data could be from multiple drives in a single computer or from multiple computers. When you make a case, it will create a directory to hold all of the information. The directory will contain the main Autopsy configuration file, other module's configuration files, some databases, generated reports, and some other information (temporary files, cache files). diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-idx.xml b/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-idx.xml index 3a719b63e9..c54f521815 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-idx.xml +++ b/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-idx.xml @@ -9,8 +9,8 @@ and open the template in the editor. - - + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-toc.xml b/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-toc.xml index 75289eb55a..47378da25a 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-toc.xml +++ b/Core/src/org/sleuthkit/autopsy/casemodule/docs/casemodule-toc.xml @@ -12,9 +12,9 @@ and open the template in the editor. - - - + + + diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/docs/overview.html b/Core/src/org/sleuthkit/autopsy/casemodule/docs/overview.html index d74a051e80..515e996174 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/docs/overview.html +++ b/Core/src/org/sleuthkit/autopsy/casemodule/docs/overview.html @@ -14,7 +14,7 @@ The remainder of the help guide is organized around these concepts.

- The main Autopsy features include: importing and image and exploring its file systems, + The main Autopsy features include: importing a Data Source (image, disk, files) and exploring its file systems, running analysis modules (ingest), viewing ingest results, viewing content and generating reports.

@@ -24,7 +24,7 @@

All data is organized around the concept of a case. - A case can have one or more disk images loaded into it. + A case can have one or more data sources loaded into it.

The main window has three major areas:

    diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java index b9bd8b85f8..f013ea6864 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/services/FileManager.java @@ -177,20 +177,22 @@ public class FileManager implements Closeable { * Adds a carved file to the VirtualDirectory '$CarvedFiles' in the volume * or file system given by systemId. * - * @param name the name of the carved file (containing appropriate + * @param carvedFileName the name of the carved file (containing appropriate * extension) + * @param carvedFileSize size of the carved file to add * @param systemId the ID of the parent volume or file system * @param sectors a list of SectorGroups giving this sectors that make up * this carved file. + * @throws TskCoreException exception thrown when critical tsk error occurred and carved file could not be added */ public synchronized LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, - long systemId, List data) throws TskCoreException { + long systemId, List sectors) throws TskCoreException { if (tskCase == null) { throw new TskCoreException("Attempted to use FileManager after it was closed."); } - return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, data); + return tskCase.addCarvedFile(carvedFileName, carvedFileSize, systemId, sectors); } /** diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java b/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java index 88e22a7307..fd64d080ce 100644 --- a/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java +++ b/Core/src/org/sleuthkit/autopsy/coreutils/PlatformUtil.java @@ -418,7 +418,7 @@ public class PlatformUtil { /** * Query and get PID of another java process * - * @sigarSubQuery a sigar subquery to identify a unique java process among + * @param sigarSubQuery a sigar subquery to identify a unique java process among * other java processes, for example, by class name, use: * Args.*.eq=org.jboss.Main more examples here: * http://support.hyperic.com/display/SIGAR/PTQL @@ -448,7 +448,7 @@ public class PlatformUtil { /** * Query and get PIDs of another java processes matching a query * - * @sigarSubQuery a sigar subquery to identify a java processes among other + * @param sigarSubQuery a sigar subquery to identify a java processes among other * java processes, for example, by class name, use: Args.*.eq=org.jboss.Main * more examples here: http://support.hyperic.com/display/SIGAR/PTQL * diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java index aba9b34ead..76ad367ace 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractContentChildren.java @@ -16,7 +16,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.sleuthkit.autopsy.datamodel; import org.openide.nodes.AbstractNode; @@ -39,14 +38,14 @@ import org.sleuthkit.datamodel.Volume; /** * Abstract subclass for ContentChildren and RootContentChildren implementations * that handles creating Nodes from Content objects. -*/ + */ abstract class AbstractContentChildren extends Keys { private final CreateSleuthkitNodeVisitor createSleuthkitNodeVisitor = new CreateSleuthkitNodeVisitor(); private final CreateAutopsyNodeVisitor createAutopsyNodeVisitor = new CreateAutopsyNodeVisitor(); - + /** - * Uses lazy Content.Keys + * Uses lazy Content.Keys */ AbstractContentChildren() { super(true); // use lazy behavior @@ -54,21 +53,18 @@ abstract class AbstractContentChildren extends Keys { @Override protected Node[] createNodes(T key) { - if(key instanceof SleuthkitVisitableItem) { + if (key instanceof SleuthkitVisitableItem) { return new Node[]{((SleuthkitVisitableItem) key).accept(createSleuthkitNodeVisitor)}; - } - else { + } else { return new Node[]{((AutopsyVisitableItem) key).accept(createAutopsyNodeVisitor)}; } } - - /** * Creates appropriate Node for each sub-class of Content */ public static class CreateSleuthkitNodeVisitor extends SleuthkitItemVisitor.Default { - + @Override public AbstractContentNode visit(Directory drctr) { return new DirectoryNode(drctr); @@ -88,22 +84,22 @@ abstract class AbstractContentChildren extends Keys { public AbstractContentNode visit(Volume volume) { return new VolumeNode(volume); } - + @Override public AbstractContentNode visit(LayoutFile lf) { return new LayoutFileNode(lf); } - + @Override public AbstractContentNode visit(DerivedFile df) { return new LocalFileNode(df); } - + @Override public AbstractContentNode visit(LocalFile lf) { return new LocalFileNode(lf); } - + @Override public AbstractContentNode visit(VirtualDirectory ld) { return new VirtualDirectoryNode(ld); @@ -114,53 +110,57 @@ abstract class AbstractContentChildren extends Keys { throw new UnsupportedOperationException("No Node defined for the given SleuthkitItem"); } } - + /** * Creates appropriate Node for each supported artifact category / grouping */ static class CreateAutopsyNodeVisitor extends AutopsyItemVisitor.Default { - + @Override public ExtractedContentNode visit(ExtractedContent ec) { return new ExtractedContentNode(ec.getSleuthkitCase()); } - + @Override public AbstractNode visit(SearchFilters sf) { - return new SearchFiltersNode(sf.getSleuthkitCase(), true); + return new SearchFiltersNode(sf.getSleuthkitCase(), null); } - + @Override public AbstractNode visit(RecentFiles rf) { return new RecentFilesNode(rf.getSleuthkitCase()); } - + @Override public AbstractNode visit(DeletedContent dc) { return new DeletedContent.DeletedContentsNode(dc.getSleuthkitCase()); } - + + @Override + public AbstractNode visit(FileSize dc) { + return new FileSize.FileSizeRootNode(dc.getSleuthkitCase()); + } + @Override public AbstractNode visit(KeywordHits kh) { return kh.new KeywordHitsRootNode(); } - + @Override public AbstractNode visit(HashsetHits hh) { return hh.new HashsetHitsRootNode(); } - + @Override public AbstractNode visit(EmailExtracted ee) { return ee.new EmailExtractedRootNode(); } - - + @Override public AbstractNode visit(Tags t) { return t.new TagsRootNode(); } - + @Override public AbstractNode visit(DataSources i) { try { @@ -169,12 +169,12 @@ abstract class AbstractContentChildren extends Keys { return defaultVisit(i); } } - + @Override public AbstractNode visit(Views v) { return new ViewsNode(v.getSleuthkitCase()); } - + @Override public AbstractNode visit(Results r) { return new ResultsNode(r.getSleuthkitCase()); @@ -185,5 +185,4 @@ abstract class AbstractContentChildren extends Keys { throw new UnsupportedOperationException("No Node defined for the given DisplayableItem"); } } - } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java index 8cba2b24ae..431c9adf27 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AutopsyItemVisitor.java @@ -23,98 +23,132 @@ package org.sleuthkit.autopsy.datamodel; * @author dfickling */ public interface AutopsyItemVisitor { - + T visit(ExtractedContent ec); + T visit(SearchFilters sf); + T visit(SearchFilters.FileSearchFilter fsf); + T visit(SearchFilters.DocumentFilter df); + + T visit(SearchFilters.ExecutableFilter ef); + T visit(RecentFiles rf); + T visit(RecentFiles.RecentFilesFilter rff); + T visit(DeletedContent dc); + T visit(DeletedContent.DeletedContentFilter dcf); + + T visit(FileSize fs); + + T visit(FileSize.FileSizeFilter fsf); + T visit(KeywordHits kh); + T visit(HashsetHits hh); + T visit(EmailExtracted ee); + T visit(Tags t); + T visit(DataSources i); + T visit(Views v); + T visit(Results r); - + static abstract public class Default implements AutopsyItemVisitor { protected abstract T defaultVisit(AutopsyVisitableItem ec); - + @Override public T visit(ExtractedContent ec) { return defaultVisit(ec); } - + @Override public T visit(SearchFilters sf) { return defaultVisit(sf); } - + @Override public T visit(SearchFilters.FileSearchFilter fsf) { return defaultVisit(fsf); } - + @Override public T visit(SearchFilters.DocumentFilter df) { return defaultVisit(df); } - - @Override + + @Override + public T visit(SearchFilters.ExecutableFilter ef) { + return defaultVisit(ef); + } + + @Override public T visit(DeletedContent dc) { return defaultVisit(dc); } - + @Override public T visit(DeletedContent.DeletedContentFilter dcf) { return defaultVisit(dcf); } - + + @Override + public T visit(FileSize fs) { + return defaultVisit(fs); + } + + @Override + public T visit(FileSize.FileSizeFilter fsf) { + return defaultVisit(fsf); + } + @Override public T visit(RecentFiles rf) { return defaultVisit(rf); } - + @Override public T visit(RecentFiles.RecentFilesFilter rff) { return defaultVisit(rff); } - + @Override public T visit(KeywordHits kh) { return defaultVisit(kh); } - + @Override public T visit(HashsetHits hh) { return defaultVisit(hh); } - + @Override public T visit(EmailExtracted ee) { return defaultVisit(ee); } - - + @Override public T visit(Tags t) { return defaultVisit(t); } - + @Override public T visit(DataSources i) { return defaultVisit(i); } - + @Override public T visit(Views v) { return defaultVisit(v); } - + @Override public T visit(Results r) { return defaultVisit(r); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java index 6ef9fca4fc..72f8bd451c 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DeletedContent.java @@ -162,13 +162,17 @@ public class DeletedContent implements AutopsyVisitableItem { DeletedContentNode(SleuthkitCase skCase, DeletedContent.DeletedContentFilter filter) { super(Children.create(new DeletedContentChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); super.setName(filter.getName()); - super.setDisplayName(filter.getDisplayName()); this.skCase = skCase; this.filter = filter; String tooltip = filter.getDisplayName(); this.setShortDescription(tooltip); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-icon-deleted.png"); + + //get count of children without preloading all children nodes + final long count = new DeletedContentChildren(filter, skCase).calculateItems(); + //final long count = getChildren().getNodesCount(true); + super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); } @Override @@ -225,30 +229,30 @@ public class DeletedContent implements AutopsyVisitableItem { String query = ""; switch (filter) { case FS_DELETED_FILTER: - query = "dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() + query = "dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() + " AND meta_flags != " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType(); - + break; case ALL_DELETED_FILTER: - query = " ( " + query = " ( " + "( " + "(dir_flags = " + TskData.TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue() + " OR " - + "meta_flags = " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() + + "meta_flags = " + TskData.TSK_FS_META_FLAG_ENUM.ORPHAN.getValue() + ")" + " AND type = " + TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType() + " )" + " OR type = " + TskData.TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType() + " )"; - //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() - //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType() - //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType() - //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType() - //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType() - //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(); + //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() + //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType() + //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType() + //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType() + //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType() + //+ " AND type != " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType(); break; - + default: logger.log(Level.SEVERE, "Unsupported filter type to get deleted content: " + filter); @@ -271,6 +275,20 @@ public class DeletedContent implements AutopsyVisitableItem { } + /** + * Get children count without actually loading all nodes + * + * @return + */ + long calculateItems() { + try { + return skCase.countFilesWhere(makeQuery()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting deleted files search view count", ex); + return 0; + } + } + @Override protected Node createNodeForKey(AbstractFile key) { return key.accept(new ContentVisitor.Default() { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java index a6c0e165fd..9072a35689 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/DisplayableItemNodeVisitor.java @@ -23,6 +23,8 @@ import org.sleuthkit.autopsy.datamodel.DeletedContent.DeletedContentsNode; import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedAccountNode; import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedFolderNode; import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode; import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode; import org.sleuthkit.autopsy.datamodel.KeywordHits.KeywordHitsKeywordNode; @@ -38,45 +40,80 @@ import org.sleuthkit.autopsy.datamodel.Tags.TagsRootNode; public interface DisplayableItemNodeVisitor { T visit(DirectoryNode dn); + T visit(FileNode fn); + T visit(ImageNode in); + T visit(VolumeNode vn); + T visit(BlackboardArtifactNode ban); + T visit(ArtifactTypeNode atn); + T visit(ExtractedContentNode ecn); + T visit(FileSearchFilterNode fsfn); + T visit(DeletedContentNode dcn); + T visit(DeletedContentsNode dcn); + + T visit(FileSizeRootNode fsrn); + + T visit(FileSizeNode fsn); + T visit(SearchFiltersNode sfn); + T visit(RecentFilesNode rfn); + T visit(RecentFilesFilterNode rffn); + T visit(KeywordHitsRootNode khrn); + T visit(KeywordHitsListNode khsn); + T visit(KeywordHitsKeywordNode khmln); + T visit(HashsetHitsRootNode hhrn); + T visit(HashsetHitsSetNode hhsn); + T visit(EmailExtractedRootNode eern); + T visit(EmailExtractedAccountNode eean); + T visit(EmailExtractedFolderNode eefn); + T visit(TagsRootNode bksrn); + T visit(TagsNodeRoot bksrn); + T visit(TagNodeRoot tnr); + T visit(ViewsNode vn); + T visit(ResultsNode rn); + T visit(DataSourcesNode in); + T visit(LayoutFileNode lfn); + T visit(LocalFileNode dfn); + T visit(VirtualDirectoryNode ldn); /** * Visitor with an implementable default behavior for all types. Override * specific visit types to not use the default behavior. + * * @param */ static abstract class Default implements DisplayableItemNodeVisitor { /** * Default visit for all types + * * @param c * @return */ @@ -103,126 +140,135 @@ public interface DisplayableItemNodeVisitor { } @Override - public T visit(BlackboardArtifactNode ban){ + public T visit(BlackboardArtifactNode ban) { return defaultVisit(ban); } @Override - public T visit(ArtifactTypeNode atn){ + public T visit(ArtifactTypeNode atn) { return defaultVisit(atn); } @Override - public T visit(ExtractedContentNode ecn){ + public T visit(ExtractedContentNode ecn) { return defaultVisit(ecn); } @Override - public T visit(FileSearchFilterNode fsfn){ + public T visit(FileSearchFilterNode fsfn) { return defaultVisit(fsfn); } - + @Override - public T visit(DeletedContentNode dcn){ - return defaultVisit(dcn); - } - - @Override - public T visit(DeletedContentsNode dcn){ + public T visit(DeletedContentNode dcn) { return defaultVisit(dcn); } @Override - public T visit(SearchFiltersNode sfn){ + public T visit(DeletedContentsNode dcn) { + return defaultVisit(dcn); + } + + @Override + public T visit(FileSizeRootNode fsrn) { + return defaultVisit(fsrn); + } + + @Override + public T visit(FileSizeNode fsn) { + return defaultVisit(fsn); + } + + @Override + public T visit(SearchFiltersNode sfn) { return defaultVisit(sfn); } - + @Override public T visit(RecentFilesNode rfn) { return defaultVisit(rfn); } - + @Override public T visit(RecentFilesFilterNode rffn) { return defaultVisit(rffn); } - + @Override public T visit(KeywordHitsRootNode khrn) { return defaultVisit(khrn); } - + @Override public T visit(KeywordHitsListNode khsn) { return defaultVisit(khsn); } - + @Override public T visit(KeywordHitsKeywordNode khmln) { return defaultVisit(khmln); } - + @Override public T visit(ViewsNode vn) { return defaultVisit(vn); } - + @Override public T visit(ResultsNode rn) { return defaultVisit(rn); } - + @Override public T visit(DataSourcesNode in) { return defaultVisit(in); } - + @Override public T visit(HashsetHitsRootNode hhrn) { return defaultVisit(hhrn); } - + @Override public T visit(HashsetHitsSetNode hhsn) { return defaultVisit(hhsn); } - + @Override public T visit(EmailExtractedRootNode eern) { return defaultVisit(eern); } - + @Override public T visit(EmailExtractedAccountNode eean) { return defaultVisit(eean); } - + @Override public T visit(EmailExtractedFolderNode eefn) { return defaultVisit(eefn); } - + @Override public T visit(LayoutFileNode lfn) { return defaultVisit(lfn); } - + @Override public T visit(LocalFileNode dfn) { return defaultVisit(dfn); } - + @Override public T visit(VirtualDirectoryNode ldn) { return defaultVisit(ldn); } - - + @Override public T visit(TagsRootNode bksrn) { return defaultVisit(bksrn); } - + @Override public T visit(TagsNodeRoot bksnr) { return defaultVisit(bksnr); @@ -232,7 +278,5 @@ public interface DisplayableItemNodeVisitor { public T visit(TagNodeRoot tnr) { return defaultVisit(tnr); } - - } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java index 01d4a052f9..cc4f6309f0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterChildren.java @@ -29,12 +29,13 @@ import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.ContentVisitor; import org.sleuthkit.datamodel.DerivedFile; +import org.sleuthkit.datamodel.Directory; import org.sleuthkit.datamodel.File; -import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; /** * Children factory for the file by type view in dir tree @@ -59,7 +60,8 @@ class FileSearchFilterChildren extends ChildFactory { private String createQuery(){ - String query = "(known IS NULL OR known != 1) AND (0"; + String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")" + + " AND (known IS NULL OR known != 1) AND (0"; for(String s : filter.getFilter()){ query += " OR name LIKE '%" + s + "'"; } @@ -74,17 +76,28 @@ class FileSearchFilterChildren extends ChildFactory { try { List res = skCase.findAllFilesWhere(createQuery()); for(AbstractFile c : res){ - if(c.isFile()){ list.add(c); - } } } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Couldn't get search results", ex); + logger.log(Level.SEVERE, "Couldn't get search results", ex); } return list; } + + /** + * Get children count without actually loading all nodes + * @return + */ + long calculateItems() { + try { + return skCase.countFilesWhere(createQuery()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting file search view count", ex); + return 0; + } + } @Override protected Node createNodeForKey(Content key) { @@ -94,6 +107,11 @@ class FileSearchFilterChildren extends ChildFactory { return new FileNode(f, false); } + @Override + public DirectoryNode visit(Directory d) { + return new DirectoryNode(d); + } + @Override public LayoutFileNode visit(LayoutFile lf) { return new LayoutFileNode(lf); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java index 8de20e0a40..2313d08429 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSearchFilterNode.java @@ -18,11 +18,9 @@ */ package org.sleuthkit.autopsy.datamodel; -import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.lookup.Lookups; -import org.sleuthkit.autopsy.datamodel.SearchFilters.FileSearchFilter; import org.sleuthkit.datamodel.SleuthkitCase; /** @@ -35,10 +33,17 @@ public class FileSearchFilterNode extends DisplayableItemNode { FileSearchFilterNode(SearchFilters.SearchFilterInterface filter, SleuthkitCase skCase) { super(Children.create(new FileSearchFilterChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); - super.setName(filter.getName()); - super.setDisplayName(filter.getDisplayName()); + this.filter = filter; this.skCase = skCase; + + super.setName(filter.getName()); + + //get count of children without preloading all children nodes + final long count = new FileSearchFilterChildren(filter, skCase).calculateItems(); + //final long count = getChildren().getNodesCount(true); + super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-filter-icon.png"); } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java new file mode 100644 index 0000000000..5a5c59fadc --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -0,0 +1,314 @@ +/* + * 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.datamodel; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.logging.Level; +import org.openide.nodes.AbstractNode; +import org.openide.nodes.ChildFactory; +import org.openide.nodes.Children; +import org.openide.nodes.Node; +import org.openide.nodes.Sheet; +import org.openide.util.lookup.Lookups; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.ContentVisitor; +import org.sleuthkit.datamodel.Directory; +import org.sleuthkit.datamodel.File; +import org.sleuthkit.datamodel.FsContent; +import org.sleuthkit.datamodel.LayoutFile; +import org.sleuthkit.datamodel.SleuthkitCase; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * Files by Size View node and related child nodes + */ +public class FileSize implements AutopsyVisitableItem { + + private SleuthkitCase skCase; + + public enum FileSizeFilter implements AutopsyVisitableItem { + + SIZE_50_200(0, "SIZE_50_200", "50 - 200MB"), + SIZE_200_1000(1, "SIZE_200_1GB", "200MB - 1GB"), + SIZE_1000_(2, "SIZE_1000+", "1GB+"); + private int id; + private String name; + private String displayName; + + private FileSizeFilter(int id, String name, String displayName) { + this.id = id; + this.name = name; + this.displayName = displayName; + + } + + public String getName() { + return this.name; + } + + public int getId() { + return this.id; + } + + public String getDisplayName() { + return this.displayName; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + } + + public FileSize(SleuthkitCase skCase) { + this.skCase = skCase; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + + public SleuthkitCase getSleuthkitCase() { + return this.skCase; + } + + public static class FileSizeRootNode extends DisplayableItemNode { + + private static final String NAME = "File Size"; + private SleuthkitCase skCase; + + FileSizeRootNode(SleuthkitCase skCase) { + super(Children.create(new FileSizeRootChildren(skCase), true), Lookups.singleton(NAME)); + super.setName(NAME); + super.setDisplayName(NAME); + this.skCase = skCase; + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); + } + + @Override + public DisplayableItemNode.TYPE getDisplayableItemNodeType() { + return DisplayableItemNode.TYPE.META; + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + + ss.put(new NodeProperty("Name", + "Name", + "no description", + NAME)); + return s; + } + } + + public static class FileSizeRootChildren extends ChildFactory { + + private SleuthkitCase skCase; + + public FileSizeRootChildren(SleuthkitCase skCase) { + this.skCase = skCase; + + } + + @Override + protected boolean createKeys(List list) { + list.addAll(Arrays.asList(FileSizeFilter.values())); + return true; + } + + @Override + protected Node createNodeForKey(FileSizeFilter key) { + return new FileSizeNode(skCase, key); + } + + public class FileSizeNode extends DisplayableItemNode { + + private SleuthkitCase skCase; + private FileSizeFilter filter; + private final Logger logger = Logger.getLogger(FileSizeNode.class.getName()); + + FileSizeNode(SleuthkitCase skCase, FileSizeFilter filter) { + super(Children.create(new FileSizeChildren(filter, skCase), true), Lookups.singleton(filter.getDisplayName())); + super.setName(filter.getName()); + this.skCase = skCase; + this.filter = filter; + + String tooltip = filter.getDisplayName(); + this.setShortDescription(tooltip); + this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file-size-16.png"); + + //get count of children without preloading all children nodes + final long count = new FileSizeChildren(filter, skCase).calculateItems(); + //final long count = getChildren().getNodesCount(true); + super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); + } + + @Override + public T accept(DisplayableItemNodeVisitor v) { + return v.visit(this); + } + + @Override + protected Sheet createSheet() { + Sheet s = super.createSheet(); + Sheet.Set ss = s.get(Sheet.PROPERTIES); + if (ss == null) { + ss = Sheet.createPropertiesSet(); + s.put(ss); + } + + ss.put(new NodeProperty("Filter Type", + "Filter Type", + "no description", + filter.getDisplayName())); + + return s; + } + + @Override + public DisplayableItemNode.TYPE getDisplayableItemNodeType() { + return DisplayableItemNode.TYPE.META; + } + + @Override + public boolean isLeafTypeNode() { + return true; + } + } + + class FileSizeChildren extends ChildFactory { + + private SleuthkitCase skCase; + private FileSizeFilter filter; + private final Logger logger = Logger.getLogger(FileSizeChildren.class.getName()); + + FileSizeChildren(FileSizeFilter filter, SleuthkitCase skCase) { + this.skCase = skCase; + this.filter = filter; + } + + @Override + protected boolean createKeys(List list) { + list.addAll(runFsQuery()); + return true; + } + + private String makeQuery() { + String query = ""; + switch (filter) { + case SIZE_50_200: + query = "size >= 50000000 AND size < 200000000"; + + break; + case SIZE_200_1000: + query = "size >= 200000000 AND size < 1000000000"; + + break; + + case SIZE_1000_: + query = "size >= 1000000000"; + break; + + default: + logger.log(Level.SEVERE, "Unsupported filter type to get files by size: " + filter); + + } + + return query; + } + + private List runFsQuery() { + List ret = new ArrayList(); + + String query = makeQuery(); + try { + ret = skCase.findAllFilesWhere(query); + } catch (TskCoreException e) { + logger.log(Level.SEVERE, "Error getting files for the file size view using: " + query, e); + } + + return ret; + + } + + /** + * Get children count without actually loading all nodes + * + * @return + */ + long calculateItems() { + try { + return skCase.countFilesWhere(makeQuery()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting files by size search view count", ex); + return 0; + } + } + + @Override + protected Node createNodeForKey(AbstractFile key) { + return key.accept(new ContentVisitor.Default() { + public FileNode visit(AbstractFile f) { + return new FileNode(f, false); + } + + public FileNode visit(FsContent f) { + return new FileNode(f, false); + } + + @Override + public FileNode visit(LayoutFile f) { + return new FileNode(f, false); + } + + @Override + public FileNode visit(File f) { + return new FileNode(f, false); + } + + @Override + public FileNode visit(Directory f) { + return new FileNode(f, false); + } + + @Override + protected AbstractNode defaultVisit(Content di) { + throw new UnsupportedOperationException("Not supported for this type of Displayable Item: " + di.toString()); + } + }); + } + } + } +} diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesChildren.java index 141a4cab30..759e906a4e 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesChildren.java @@ -36,8 +36,8 @@ import org.sleuthkit.datamodel.SleuthkitCase; */ public class RecentFilesChildren extends ChildFactory { - SleuthkitCase skCase; - Calendar lastDay; + private SleuthkitCase skCase; + private Calendar lastDay; private final static Logger logger = Logger.getLogger(RecentFilesChildren.class.getName()); public RecentFilesChildren(SleuthkitCase skCase) { @@ -74,8 +74,9 @@ public class RecentFilesChildren extends ChildFactory { - SleuthkitCase skCase; - RecentFilesFilter filter; - Calendar prevDay; + private SleuthkitCase skCase; + private RecentFilesFilter filter; + private Calendar prevDay; private final static Logger logger = Logger.getLogger(RecentFilesFilterChildren.class.getName()); //private final static int MAX_OBJECTS = 1000000; @@ -55,16 +59,18 @@ public class RecentFilesFilterChildren extends ChildFactory { @Override protected boolean createKeys(List list) { - list.addAll(runFsQuery()); + list.addAll(runQuery()); return true; } private String createQuery() { - String query = "(known IS NULL OR known != 1) AND ("; - long lowerLimit = prevDay.getTimeInMillis() / 1000; - prevDay.add(Calendar.DATE, 1); - prevDay.add(Calendar.MILLISECOND, -1); - long upperLimit = prevDay.getTimeInMillis() / 1000; + Calendar prevDayQuery = (Calendar) prevDay.clone(); + String query = "(dir_type = " + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + ")" + + " AND (known IS NULL OR known != 1) AND ("; + long lowerLimit = prevDayQuery.getTimeInMillis() / 1000; + prevDayQuery.add(Calendar.DATE, 1); + prevDayQuery.add(Calendar.MILLISECOND, -1); + long upperLimit = prevDayQuery.getTimeInMillis() / 1000; query += "(crtime BETWEEN " + lowerLimit + " AND " + upperLimit + ") OR "; query += "(ctime BETWEEN " + lowerLimit + " AND " + upperLimit + ") OR "; //query += "(atime BETWEEN " + lowerLimit + " AND " + upperLimit + ") OR "; @@ -73,14 +79,12 @@ public class RecentFilesFilterChildren extends ChildFactory { return query; } - private List runFsQuery() { - List ret = new ArrayList(); + private List runQuery() { + List ret = new ArrayList(); try { - List found = skCase.findFilesWhere(createQuery()); - for (FsContent c : found) { - if (c.isFile()) { + List found = skCase.findAllFilesWhere(createQuery()); + for (AbstractFile c : found) { ret.add(c); - } } } catch (TskCoreException ex) { @@ -89,6 +93,21 @@ public class RecentFilesFilterChildren extends ChildFactory { return ret; } + + /** + * Get children count without actually loading all nodes + * @return + */ + long calculateItems() { + try { + return skCase.countFilesWhere(createQuery()); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting recent files search view count", ex); + return 0; + } + } + + @Override protected Node createNodeForKey(Content key) { @@ -97,7 +116,23 @@ public class RecentFilesFilterChildren extends ChildFactory { public FileNode visit(File f) { return new FileNode(f, false); } - + + @Override + public DirectoryNode visit(Directory d) { + return new DirectoryNode(d); + } + + @Override + public LocalFileNode visit(DerivedFile f) { + return new LocalFileNode(f); + } + + @Override + public LocalFileNode visit(LocalFile f) { + return new LocalFileNode(f); + } + + @Override protected AbstractNode defaultVisit(Content di) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesFilterNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesFilterNode.java index 54ae72dc74..a2b9bf9d46 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesFilterNode.java @@ -40,7 +40,7 @@ public class RecentFilesFilterNode extends DisplayableItemNode { RecentFilesFilterNode(SleuthkitCase skCase, RecentFilesFilter filter, Calendar lastDay) { super(Children.create(new RecentFilesFilterChildren(filter, skCase, lastDay), true), Lookups.singleton(filter.getDisplayName())); super.setName(filter.getName()); - super.setDisplayName(filter.getDisplayName()); + //super.setDisplayName(filter.getDisplayName()); this.skCase = skCase; this.filter = filter; Calendar prevDay = (Calendar) lastDay.clone(); @@ -50,6 +50,11 @@ public class RecentFilesFilterNode extends DisplayableItemNode { + prevDay.get(Calendar.YEAR); this.setShortDescription(tooltip); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/recent_files.png"); + + //get count of children without preloading all children nodes + final long count = new RecentFilesFilterChildren(filter, skCase, lastDay).calculateItems(); + //final long count = getChildren().getNodesCount(true); + super.setDisplayName(filter.getDisplayName() + " (" + count + ")"); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesNode.java index bb98d75540..91958d0b97 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/RecentFilesNode.java @@ -30,7 +30,7 @@ import org.sleuthkit.datamodel.SleuthkitCase; public class RecentFilesNode extends DisplayableItemNode { private static final String NAME = "Recent Files"; - SleuthkitCase skCase; + private SleuthkitCase skCase; RecentFilesNode(SleuthkitCase skCase) { super(Children.create(new RecentFilesChildren(skCase), true), Lookups.singleton(NAME)); @@ -38,6 +38,7 @@ public class RecentFilesNode extends DisplayableItemNode { super.setDisplayName(NAME); this.skCase = skCase; this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/recent_files.png"); + } @Override diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java index ac4f4c8976..4bdbe641b7 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFilters.java @@ -33,7 +33,9 @@ public class SearchFilters implements AutopsyVisitableItem { TSK_IMAGE_FILTER(0, "TSK_IMAGE_FILTER", "Images", FileTypeExtensions.getImageExtensions()), TSK_VIDEO_FILTER(1, "TSK_VIDEO_FILTER", "Videos", FileTypeExtensions.getVideoExtensions()), TSK_AUDIO_FILTER(2, "TSK_AUDIO_FILTER", "Audio", FileTypeExtensions.getAudioExtensions()), - TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", "Documents", Arrays.asList(".doc", ".docx", ".pdf", ".xls", ".rtf", ".txt")); + TSK_ARCHIVE_FILTER(3, "TSK_ARCHIVE_FILTER", "Archives", FileTypeExtensions.getArchiveExtensions()), + TSK_DOCUMENT_FILTER(3, "TSK_DOCUMENT_FILTER", "Documents", Arrays.asList(".doc", ".docx", ".pdf", ".xls", ".rtf", ".txt")), + TSK_EXECUTABLE_FILTER(3, "TSK_EXECUTABLE_FILTER", "Executable", Arrays.asList(".exe", ".dll", ".bat", ".cmd", ".com")); private int id; private String name; @@ -81,10 +83,10 @@ public class SearchFilters implements AutopsyVisitableItem { AUT_DOC_TXT(3, "AUT_DOC_TXT", "Plain Text", Arrays.asList(".txt")), AUT_DOC_RTF(4, "AUT_DOC_RTF", "Rich Text", Arrays.asList(".rtf")); - int id; - String name; - String displayName; - List filter; + private int id; + private String name; + private String displayName; + private List filter; private DocumentFilter(int id, String name, String displayName, List filter){ this.id = id; @@ -118,6 +120,52 @@ public class SearchFilters implements AutopsyVisitableItem { return this.filter; } } + + + public enum ExecutableFilter implements AutopsyVisitableItem,SearchFilterInterface { + ExecutableFilter_EXE(0, "ExecutableFilter_EXE", ".exe", Arrays.asList(".exe")), + ExecutableFilter_DLL(1, "ExecutableFilter_DLL", ".dll", Arrays.asList(".dll")), + ExecutableFilter_BAT(2, "ExecutableFilter_BAT", ".bat", Arrays.asList(".bat")), + ExecutableFilter_CMD(3, "ExecutableFilter_CMD", ".cmd", Arrays.asList(".cmd")), + ExecutableFilter_COM(4, "ExecutableFilter_COM", ".com", Arrays.asList(".com")); + + private int id; + private String name; + private String displayName; + private List filter; + + private ExecutableFilter(int id, String name, String displayName, List filter){ + this.id = id; + this.name = name; + this.displayName = displayName; + this.filter = filter; + } + + @Override + public T accept(AutopsyItemVisitor v) { + return v.visit(this); + } + + @Override + public String getName(){ + return this.name; + } + + @Override + public int getId(){ + return this.id; + } + + @Override + public String getDisplayName(){ + return this.displayName; + } + + @Override + public List getFilter(){ + return this.filter; + } + } public SearchFilters(SleuthkitCase skCase){ this.skCase = skCase; diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java index 95e928d6d4..cdc1109a47 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersChildren.java @@ -31,28 +31,38 @@ import org.sleuthkit.datamodel.SleuthkitCase; class SearchFiltersChildren extends ChildFactory { private SleuthkitCase skCase; - private boolean root; + private SearchFilters.FileSearchFilter filter; - public SearchFiltersChildren(SleuthkitCase skCase, boolean root) { + public SearchFiltersChildren(SleuthkitCase skCase, SearchFilters.FileSearchFilter filter) { this.skCase = skCase; - this.root = root; + this.filter = filter; } @Override protected boolean createKeys(List list) { - if(root) + if (filter == null) { list.addAll(Arrays.asList(FileSearchFilter.values())); - else + } + else if (filter.equals(FileSearchFilter.TSK_DOCUMENT_FILTER) ){ list.addAll(Arrays.asList(SearchFilters.DocumentFilter.values())); + } + else if (filter.equals(FileSearchFilter.TSK_EXECUTABLE_FILTER) ){ + list.addAll(Arrays.asList(SearchFilters.ExecutableFilter.values())); + } return true; } @Override protected Node createNodeForKey(SearchFilters.SearchFilterInterface key){ if(key.getName().equals(SearchFilters.FileSearchFilter.TSK_DOCUMENT_FILTER.getName())){ - return new SearchFiltersNode(skCase, false); + return new SearchFiltersNode(skCase, SearchFilters.FileSearchFilter.TSK_DOCUMENT_FILTER); + } + else if(key.getName().equals(SearchFilters.FileSearchFilter.TSK_EXECUTABLE_FILTER.getName())){ + return new SearchFiltersNode(skCase, SearchFilters.FileSearchFilter.TSK_EXECUTABLE_FILTER); + } + else { + return new FileSearchFilterNode(key, skCase); } - return new FileSearchFilterNode(key, skCase); } } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java index 50b5731a58..6eabf8cc79 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/SearchFiltersNode.java @@ -18,7 +18,6 @@ */ package org.sleuthkit.autopsy.datamodel; -import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; import org.openide.nodes.Sheet; import org.openide.util.lookup.Lookups; @@ -30,17 +29,16 @@ import org.sleuthkit.datamodel.SleuthkitCase; public class SearchFiltersNode extends DisplayableItemNode { private static final String FNAME = "File Types"; - private static final String DNAME = "Documents"; - SleuthkitCase skCase; + private SleuthkitCase skCase; - SearchFiltersNode(SleuthkitCase skCase, boolean root) { - super(Children.create(new SearchFiltersChildren(skCase, root), true), Lookups.singleton(root ? FNAME : DNAME)); - if (root) { + SearchFiltersNode(SleuthkitCase skCase, SearchFilters.FileSearchFilter filter) { + super(Children.create(new SearchFiltersChildren(skCase, filter), true), Lookups.singleton(filter == null ? FNAME : filter.getName())); + if (filter == null) { super.setName(FNAME); super.setDisplayName(FNAME); } else { - super.setName(DNAME); - super.setDisplayName(DNAME); + super.setName(filter.getName()); + super.setDisplayName(filter.getDisplayName()); } this.skCase = skCase; this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/file_types.png"); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java index cddf6c5423..eea33be974 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/ViewsNode.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.datamodel; import java.util.Arrays; -import org.openide.nodes.AbstractNode; import org.openide.nodes.Sheet; import org.openide.util.lookup.Lookups; import org.sleuthkit.datamodel.SleuthkitCase; @@ -34,7 +33,13 @@ public class ViewsNode extends DisplayableItemNode { public static final String NAME = "Views"; public ViewsNode(SleuthkitCase sleuthkitCase) { - super(new RootContentChildren(Arrays.asList(new SearchFilters(sleuthkitCase), new RecentFiles(sleuthkitCase), new DeletedContent(sleuthkitCase))), Lookups.singleton(NAME)); + super(new RootContentChildren(Arrays.asList( + new SearchFilters(sleuthkitCase), + new RecentFiles(sleuthkitCase), + new DeletedContent(sleuthkitCase), + new FileSize(sleuthkitCase) + )), + Lookups.singleton(NAME)); setName(NAME); setDisplayName(NAME); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/views.png"); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index d7e010b49c..a439a066bf 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -48,6 +48,8 @@ import org.sleuthkit.autopsy.datamodel.EmailExtracted.EmailExtractedRootNode; import org.sleuthkit.autopsy.datamodel.ExtractedContentNode; import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.datamodel.FileSearchFilterNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootChildren.FileSizeNode; +import org.sleuthkit.autopsy.datamodel.FileSize.FileSizeRootNode; import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsRootNode; import org.sleuthkit.autopsy.datamodel.HashsetHits.HashsetHitsSetNode; import org.sleuthkit.autopsy.datamodel.ImageNode; @@ -365,17 +367,27 @@ public class DataResultFilterNode extends FilterNode { public AbstractAction visit(RecentFilesNode rfn) { return openChild(rfn); } - + @Override public AbstractAction visit(DeletedContentsNode dcn) { return openChild(dcn); } - + @Override public AbstractAction visit(DeletedContentNode dcn) { return openChild(dcn); } + @Override + public AbstractAction visit(FileSizeRootNode fsrn) { + return openChild(fsrn); + } + + @Override + public AbstractAction visit(FileSizeNode fsn) { + return openChild(fsn); + } + @Override public AbstractAction visit(BlackboardArtifactNode ban) { return new ViewContextAction("View in Directory", ban); diff --git a/Core/src/org/sleuthkit/autopsy/images/file-size-16.png b/Core/src/org/sleuthkit/autopsy/images/file-size-16.png new file mode 100644 index 0000000000..d7dfc85b75 Binary files /dev/null and b/Core/src/org/sleuthkit/autopsy/images/file-size-16.png differ diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java index c6e3e32eaa..8b1299b15c 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestDialogPanel.java @@ -325,7 +325,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi } }); save(); // save the simple panel - dialog.display(currentModule.getAdvancedConfiguration()); + dialog.display(currentModule.getAdvancedConfiguration(null)); }//GEN-LAST:event_advancedButtonActionPerformed private void processUnallocCheckboxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_processUnallocCheckboxActionPerformed @@ -452,7 +452,7 @@ public class IngestDialogPanel extends javax.swing.JPanel implements IngestConfi if(this.modulesTable.getSelectedRow() != -1) { simplePanel.removeAll(); if (currentModule.hasSimpleConfiguration()) { - simplePanel.add(currentModule.getSimpleConfiguration()); + simplePanel.add(currentModule.getSimpleConfiguration(null)); } simplePanel.revalidate(); simplePanel.repaint(); diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java index f772c54863..b51b93122f 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleAbstract.java @@ -101,7 +101,7 @@ public abstract class IngestModuleAbstract { /** - * Gets the arguments as set in XML + * Gets the module arguments as set in pipeline/module configuration * @return arguments string */ public String getArguments() { @@ -109,11 +109,11 @@ public abstract class IngestModuleAbstract { } /** - * Sets the arguments from XML - * @param args arguments string in XML + * Sets the module arguments (e.g. from pipeline/module configuration) + * @param moduleArgs arguments string */ - public void setArguments(String a_args) { - args = a_args; + public void setArguments(String moduleArgs) { + args = moduleArgs; } /** @@ -162,27 +162,34 @@ public abstract class IngestModuleAbstract { public void saveAdvancedConfiguration() {} /** - * Returns a panel that displays the simple (run-time) configuration. + * Returns a panel that displays the simple (run-time) configuration + * for the given configuration context (such as pipeline instance). * This is presented to the user before ingest starts and only basic - * settings should be given here. use the advanced (general) configuration + * settings should be given here. Use the advanced (general) configuration * panel for more in-depth interfaces. - * The module is responsible for preserving / saving its configuration state - * In addition, saveSimpleConfiguration() can be used + * The module (or its configuration controller object) is responsible for preserving / saving its configuration state + * In addition, saveSimpleConfiguration() can be used as the trigger. * + * @param context the configuration context to use in the panel * @return JPanel containing basic configuration widgets or null if simple configuration is not available */ - public javax.swing.JPanel getSimpleConfiguration() { + public javax.swing.JPanel getSimpleConfiguration(String context) { return null; } /** - * Implements advanced module conf iguration exposed to the user before ingest starts - * The module is responsible for preserving / saving its configuration state - * In addition, saveAdvancedConfiguration() can be used + * Returns a panel that displays the advanced (run-time) configuration + * for the given configuration context (such as pipeline instance). + * Implements advanced module configuration exposed to the user before ingest starts. * + * The module (or its configuration controller object) + * is responsible for preserving / saving its configuration state + * In addition, saveAdvancedConfiguration() can be used as the trigger. + * + * @param context the configuration context to use in the panel * @return JPanel containing advanced configuration widgets or null if advanced configuration is not available */ - public javax.swing.JPanel getAdvancedConfiguration() { + public javax.swing.JPanel getAdvancedConfiguration(String context) { return null; }; } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/docs/ingest-about.html b/Core/src/org/sleuthkit/autopsy/ingest/docs/ingest-about.html index 1e82a8f3ab..73892dc849 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/docs/ingest-about.html +++ b/Core/src/org/sleuthkit/autopsy/ingest/docs/ingest-about.html @@ -25,7 +25,7 @@ and even for very large images to be processed there can be initial results available minutes, sometimes seconds after the analysis has started.

    - You can start image ingest in two ways. When you add an image with the Add Image wizard, + You can start image ingest in two ways. When you add an image with the Add Data Source wizard, you will be shown the list of ingest modules and you can choose which you want to run. You can also launch the Ingest Manager run ingest by right clicking on an image in the explorer tree and choosing "Restart Image Ingest".

    diff --git a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java index 5cfc8d9454..8cf87ce28c 100644 --- a/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java +++ b/HashDatabase/src/org/sleuthkit/autopsy/hashdatabase/HashDbIngestModule.java @@ -222,13 +222,13 @@ public class HashDbIngestModule extends IngestModuleAbstractFile { } @Override - public javax.swing.JPanel getSimpleConfiguration() { + public javax.swing.JPanel getSimpleConfiguration(String context) { HashDbXML.getCurrent().reload(); return new HashDbSimplePanel(); } @Override - public javax.swing.JPanel getAdvancedConfiguration() { + public javax.swing.JPanel getAdvancedConfiguration(String context) { //return HashDbManagementPanel.getDefault(); getPanel().load(); return getPanel(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java index 0a883a23d7..c6d3538fc8 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchIngestModule.java @@ -427,13 +427,13 @@ public final class KeywordSearchIngestModule extends IngestModuleAbstractFile { } @Override - public javax.swing.JPanel getSimpleConfiguration() { + public javax.swing.JPanel getSimpleConfiguration(String context) { KeywordSearchListsXML.getCurrent().reload(); return new KeywordSearchIngestSimplePanel(); } @Override - public javax.swing.JPanel getAdvancedConfiguration() { + public javax.swing.JPanel getAdvancedConfiguration(String context) { //return KeywordSearchConfigurationPanel.getDefault(); getPanel().load(); return getPanel(); diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java index 16425694cd..d107def4df 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Server.java @@ -359,7 +359,7 @@ public class Server { } else { loggingPropertiesFilePath += "logging-release.properties"; } - //loggingPropertiesFilePath = PlatformUtil.getOSFilePath(loggingPropertiesFilePath); + final String loggingProperties = loggingPropertiesOpt + loggingPropertiesFilePath; final String [] SOLR_START_CMD = { @@ -371,7 +371,13 @@ public class Server { loggingProperties, "-jar", "start.jar"}; - logger.log(Level.INFO, "Starting Solr using: " + SOLR_START_CMD); + + StringBuilder cmdSb = new StringBuilder(); + for (int i = 0; iRecent Files showing inconsistent results when clicked many times ---------------- VERSION 3.0.5 -------------- diff --git a/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/ScalpelCarverIngestModule.java b/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/ScalpelCarverIngestModule.java index 33720517e5..5abeb7d0ef 100644 --- a/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/ScalpelCarverIngestModule.java +++ b/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/ScalpelCarverIngestModule.java @@ -311,12 +311,12 @@ public class ScalpelCarverIngestModule { // disable autodiscovery for now // imp public void saveAdvancedConfiguration() { } // @Override - public JPanel getSimpleConfiguration() { + public JPanel getSimpleConfiguration(String context) { throw new UnsupportedOperationException("Not supported yet."); } // @Override - public JPanel getAdvancedConfiguration() { + public JPanel getAdvancedConfiguration(String context) { throw new UnsupportedOperationException("Not supported yet."); } diff --git a/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/jni/ScalpelCarver.java b/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/jni/ScalpelCarver.java index e8d91d0571..266d989d2a 100644 --- a/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/jni/ScalpelCarver.java +++ b/ScalpelCarver/src/org/sleuthkit/autopsy/scalpel/jni/ScalpelCarver.java @@ -156,7 +156,7 @@ public class ScalpelCarver { File outputFile = new File(outputFolderPath, SCALPEL_OUTPUT_FILE_NAME); // parse the output - List output = Collections.EMPTY_LIST; + List output = Collections.emptyList(); try { output = ScalpelOutputParser.parse(outputFile); } catch (FileNotFoundException ex) { diff --git a/SevenZip/manifest.mf b/SevenZip/manifest.mf index 1b94aafc68..22d9bf88ad 100644 --- a/SevenZip/manifest.mf +++ b/SevenZip/manifest.mf @@ -2,5 +2,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.sleuthkit.autopsy.sevenzip/1 OpenIDE-Module-Implementation-Version: 1 OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/sevenzip/Bundle.properties -OpenIDE-Module-Specification-Version: 1.0 + diff --git a/SevenZip/nbproject/project.properties b/SevenZip/nbproject/project.properties index 839c46575c..1dad6ce7d2 100644 --- a/SevenZip/nbproject/project.properties +++ b/SevenZip/nbproject/project.properties @@ -4,3 +4,5 @@ license.file=../LICENSE-2.0.txt nbm.homepage=http://www.sleuthkit.org/autopsy/ nbm.module.author=Brian Carrier nbm.needs.restart=true +spec.version.base=1.0.0 + diff --git a/Timeline/manifest.mf b/Timeline/manifest.mf index 8aeb1a6102..0309715a4e 100644 --- a/Timeline/manifest.mf +++ b/Timeline/manifest.mf @@ -1,8 +1,7 @@ Manifest-Version: 1.0 -OpenIDE-Module: org.sleuthkit.autopsy.timeline +OpenIDE-Module: org.sleuthkit.autopsy.timeline/1 OpenIDE-Module-Layer: org/sleuthkit/autopsy/timeline/layer.xml OpenIDE-Module-Localizing-Bundle: org/sleuthkit/autopsy/timeline/Bundle.properties OpenIDE-Module-Requires: org.openide.windows.WindowManager -OpenIDE-Module-Specification-Version: 1.0 OpenIDE-Module-Implementation-Version: 1 diff --git a/Timeline/nbproject/project.properties b/Timeline/nbproject/project.properties index 6baf44e2f5..8e20c77c1a 100644 --- a/Timeline/nbproject/project.properties +++ b/Timeline/nbproject/project.properties @@ -1,2 +1,6 @@ javac.source=1.7 javac.compilerargs=-Xlint -Xlint:-serial +license.file=../LICENSE-2.0.txt +nbm.homepage=http://www.sleuthkit.org/autopsy/ +nbm.needs.restart=true +spec.version.base=1.0.0 diff --git a/Timeline/src/org/sleuthkit/autopsy/timeline/Timeline.java b/Timeline/src/org/sleuthkit/autopsy/timeline/Timeline.java index bb4f59cc0e..1c2d29400e 100644 --- a/Timeline/src/org/sleuthkit/autopsy/timeline/Timeline.java +++ b/Timeline/src/org/sleuthkit/autopsy/timeline/Timeline.java @@ -80,7 +80,6 @@ import org.openide.modules.ModuleInstall; import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; -import org.openide.util.Exceptions; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.util.actions.CallableSystemAction; @@ -99,15 +98,11 @@ import org.sleuthkit.autopsy.datamodel.FileNode; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.coreutils.ExecUtil; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Directory; -import org.sleuthkit.datamodel.File; -import org.sleuthkit.datamodel.FsContent; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; -import org.sleuthkit.datamodel.TskData; @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.timeline.Timeline") -@ActionRegistration(displayName = "#CTL_MakeTimeline") +@ActionRegistration(displayName = "#CTL_MakeTimeline", lazy=false) @ActionReferences(value = { @ActionReference(path = "Menu/Tools", position = 100)}) @NbBundle.Messages(value = "CTL_TimelineView=Generate Timeline") @@ -121,14 +116,14 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, private HBox fxHBoxCharts; //Holds the navigation buttons in horiztonal fashion. private VBox fxVBox; //Holds the JavaFX Elements in vertical fashion. private JFXPanel fxPanelCharts; //FX panel to hold the group - private BarChart fxChartEvents; //Yearly/Monthly events - Bar chart + private BarChart fxChartEvents; //Yearly/Monthly events - Bar chart private ScrollPane fxScrollEvents; //Scroll Panes for dealing with oversized an oversized chart private static final int FRAME_HEIGHT = 700; //Sizing constants private static final int FRAME_WIDTH = 1200; private Button fxZoomOutButton; //Navigation buttons private ComboBox fxDropdownSelectYears; //Dropdown box for selecting years. Useful when the charts' scale means some years are unclickable, despite having events. - private final Stack fxStackPrevCharts = new Stack(); //Stack for storing drill-up information. - private BarChart fxChartTopLevel; //the topmost chart, used for resetting to default view. + private final Stack> fxStackPrevCharts = new Stack>(); //Stack for storing drill-up information. + private BarChart fxChartTopLevel; //the topmost chart, used for resetting to default view. private DataResultPanel dataResultPanel; private DataContentPanel dataContentPanel; private ProgressHandle progress; @@ -138,8 +133,8 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, private boolean listeningToAddImage = false; private long lastObjectId = -1; private TimelineProgressDialog progressDialog; - private EventHandler fxMouseEnteredListener; - private EventHandler fxMouseExitedListener; + private EventHandler fxMouseEnteredListener; + private EventHandler fxMouseExitedListener; private SleuthkitCase skCase; private boolean fxInited = false; @@ -270,14 +265,14 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, lsi.add(ye.year + " : " + ye.getNumFiles()); } ObservableList listSelect = FXCollections.observableArrayList(lsi); - fxDropdownSelectYears = new ComboBox(listSelect); + fxDropdownSelectYears = new ComboBox(listSelect); //Buttons for navigating up and down the timeline fxZoomOutButton = new Button("Zoom Out"); fxZoomOutButton.setOnAction(new EventHandler() { @Override public void handle(ActionEvent e) { - BarChart bc; + BarChart bc; if (fxStackPrevCharts.size() == 0) { bc = fxChartTopLevel; } else { @@ -344,7 +339,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, * @param allYears The list of years that have barData from the mactime file * @return BarChart scaled to the year level */ - private BarChart createYearChartWithDrill(final List allYears) { + private BarChart createYearChartWithDrill(final List allYears) { final CategoryAxis xAxis = new CategoryAxis(); //Axes are very specific types. Categorys are strings. final NumberAxis yAxis = new NumberAxis(); final Label l = new Label(""); @@ -372,7 +367,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, // But it is for this reason that the chart generating functions have two forloops. I do not believe they can be condensed into a single loop due to the nodes being null until // an undetermined point in time. BarChart bc = new BarChart(xAxis, yAxis, bcData); - for (final BarChart.Data barData : bc.getData().get(0).getData()) { //.get(0) refers to the BarChart.Series class to work on. There is only one series in this graph, so get(0) is safe. + for (final BarChart.Data barData : bc.getData().get(0).getData()) { //.get(0) refers to the BarChart.Series class to work on. There is only one series in this graph, so get(0) is safe. barData.getNode().setScaleX(.5); final javafx.scene.Node barNode = barData.getNode(); @@ -390,7 +385,8 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, Platform.runLater(new Runnable() { @Override public void run() { - BarChart b = createMonthsWithDrill((YearEpoch) findYear(allYears, Integer.valueOf((String) barData.getXValue()))); + BarChart b = + createMonthsWithDrill(findYear(allYears, Integer.valueOf(barData.getXValue()))); fxChartEvents = b; fxScrollEvents.setContent(fxChartEvents); } @@ -412,7 +408,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, * Displays a chart with events from one year only, separated into 1-month chunks. * Always 12 per year, empty months are represented by no bar. */ - private BarChart createMonthsWithDrill(final YearEpoch ye) { + private BarChart createMonthsWithDrill(final YearEpoch ye) { final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); @@ -431,7 +427,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, final BarChart bc = new BarChart(xAxis, yAxis, bcData); for (int i = 0; i < 12; i++) { - for (final BarChart.Data barData : bc.getData().get(0).getData()) { + for (final BarChart.Data barData : bc.getData().get(0).getData()) { //Note: // All the charts of this package have a problem where when the chart gets below a certain pixel ratio, the barData stops drawing. The axes and the labels remain, // But the actual chart barData is invisible, unclickable, and unrendered. To partially compensate for that, barData.getNode() can be manually scaled up to increase visibility. @@ -454,7 +450,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, Platform.runLater(new Runnable() { @Override public void run() { - fxChartEvents = createEventsByMonth(findMonth(ye.months, monthStringToInt((String) barData.getXValue())), ye); + fxChartEvents = createEventsByMonth(findMonth(ye.months, monthStringToInt(barData.getXValue())), ye); fxScrollEvents.setContent(fxChartEvents); } }); @@ -477,20 +473,22 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, * Displays a chart with events from one month only. * Up to 31 days per month, as low as 28 as determined by the specific MonthEpoch */ - private BarChart createEventsByMonth(final MonthEpoch me, final YearEpoch ye) { + private BarChart createEventsByMonth(final MonthEpoch me, final YearEpoch ye) { final CategoryAxis xAxis = new CategoryAxis(); final NumberAxis yAxis = new NumberAxis(); xAxis.setLabel("Day of Month"); yAxis.setLabel("Number of Events"); - ObservableList bcData = makeObservableListByMonthAllDays(me, ye.getYear()); - BarChart.Series series = new BarChart.Series(bcData); + ObservableList> bcData + = makeObservableListByMonthAllDays(me, ye.getYear()); + BarChart.Series series = new BarChart.Series(bcData); series.setName(me.getMonthName() + " " + ye.getYear()); - ObservableList> ol = FXCollections.observableArrayList(series); + ObservableList> ol = + FXCollections.>observableArrayList(series); final BarChart bc = new BarChart(xAxis, yAxis, ol); - for (final BarChart.Data barData : bc.getData().get(0).getData()) { + for (final BarChart.Data barData : bc.getData().get(0).getData()) { //data.getNode().setScaleX(2); final javafx.scene.Node barNode = barData.getNode(); @@ -505,7 +503,7 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, @Override public void handle(MouseEvent e) { - final int day = (Integer.valueOf(((String) barData.getXValue()).split("-")[1])); + final int day = (Integer.valueOf((barData.getXValue()).split("-")[1])); final DayEpoch de = myme.getDay(day); final List afs; if (de != null) { @@ -535,13 +533,13 @@ public class Timeline extends CallableSystemAction implements Presenter.Toolbar, return bc; } - private static ObservableList makeObservableListByMonthAllDays(final MonthEpoch me, int year) { - ObservableList bcData = FXCollections.observableArrayList(); + private static ObservableList> makeObservableListByMonthAllDays(final MonthEpoch me, int year) { + ObservableList> bcData = FXCollections.observableArrayList(); int totalDays = me.getTotalNumDays(year); for (int i = 1; i <= totalDays; ++i) { DayEpoch day = me.getDay(i); int numFiles = day == null ? 0 : day.getNumFiles(); - BarChart.Data d = new BarChart.Data(me.month + 1 + "-" + i, numFiles); + BarChart.Data d = new BarChart.Data(me.month + 1 + "-" + i, numFiles); d.setExtraValue(me); bcData.add(d); } diff --git a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties index db72dad058..e5590ed3f3 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,11 +1,11 @@ #Updated by build script -#Thu, 23 May 2013 00:04:58 -0400 +#Sun, 02 Jun 2013 00:12:29 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=288 SPLASH_WIDTH=538 -SplashProgressBarBounds=3,236,533,6 -SplashRunningTextBounds=5,212,530,17 +SplashProgressBarBounds=3,282,533,6 +SplashRunningTextBounds=5,266,530,17 SplashRunningTextColor=0x0 SplashRunningTextFontSize=18 -currentVersion=Autopsy 20130523 +currentVersion=Autopsy 20130602 diff --git a/docs/QuickStartGuide/index.html b/docs/QuickStartGuide/index.html index 5f74eee532..8a6d9f9f03 100644 --- a/docs/QuickStartGuide/index.html +++ b/docs/QuickStartGuide/index.html @@ -26,10 +26,10 @@

    Note that Autopsy 3 is a complete rewrite from Autopsy 2 and none of this document is relevant to Autopsy 2.

    -

    Adding a Disk Image

    +

    Adding a Data Source (image, local disk, logical files)

    - Disk images are added to a case. A case can have a single image or it can have multiple images if they are related. - Currently, a single report is generated for an entire case, so if you need to report on individual images, then you should use one image per case. + Data sources are added to a case. A case can have a single data source or it can have multiple data source if they are related. + Currently, a single report is generated for an entire case, so if you need to report on individual data sources, then you should use one data source per case.

    Creating a Case

    @@ -40,16 +40,32 @@

    -

    Adding an Image

    +

    Adding a Data Source

    - The next step is to add a disk image to the case. - The Add Image Wizard will start automatically after the case is created or you can manually start it from the "File" menu or toolbar. - You will need to supply it with the location of the disk image to add. Autopsy currently supports E01 and raw (dd) files. - You need to specify only the first file in an image set (i.e. the E01 file) and Autopsy will find the rest of the files. + The next step is to add input data source to the case. + The Add Data Source Wizard will start automatically after the case is created or you can manually start it from the "File" menu or toolbar. + You will need to choose the type of input data source to add (image, local disk or logical files and folders). + Next, supply it with the location of the source to add.

    +
      +
    • For image, point to location of disk image on your system. Autopsy currently supports E01 and raw (dd) files. + For multi-part/split images, you will need to specify only the first file in an image set (i.e. the E01 file) and Autopsy will find the rest of the files. +
    • +
    • + For local disk, select one of the detected disks. + Autopsy will add the current view of the disk to the case (i.e. snapshot of the meta-data). + However, the individual file content (not meta-data) does get updated with the changes made to the disk. + + + Note, you may need run Autopsy as an Administrator to detect all disks. +
    • +
    • For logical files, add one or more local files or folders on your system.
    • +
    + +

    - It may take a few minutes to add the disk image. + It may take a few minutes to add the data source to the case. During this time, an internal database is being created of the file system contents.

    @@ -105,7 +121,9 @@ Autopsy Screenshot

    You will start all of your analysis techniques from the tree on the left.

      -
    • The Images node shows the file system structure of the disk images.
    • +
    • The Data Sources root node shows all data in the case.
    • +
    • The individual image nodes show the file system structure of the disk images or local disks in the case.
    • +
    • The LogicalFileSet nodes show the logical files in the case.
    • The Views node shows the same data from a file type or timeline perspective.
    • The Results node shows the output from the ingest modules.
    @@ -157,7 +175,7 @@

    Known Bad Hash Files

    - If you want to see if the image had known bad files, make sure that the Hash Lookup ingest module was enabled. + If you want to see if the data source had known bad files, make sure that the Hash Lookup ingest module was enabled. You can then view the "Hashset Hits" section in the "Results" area of the tree on the left. Note that hash lookup can take a long time, so this section will be updated as long as the ingest process is occurring. Use the Ingest Inbox to keep track of what known bad files were recently found. @@ -167,7 +185,7 @@ You may find additional files that are relevant and stored in the same folder as this file.

    -

    Images and Videos

    +

    Media: Images and Videos

    If you want to see all images and video on the disk image, then go to the "Views" section in the tree on the left and then "File Types". Select either "Images" or "Videos". diff --git a/nbproject/project.properties b/nbproject/project.properties index 9e98bfbc0a..e671be54f8 100644 --- a/nbproject/project.properties +++ b/nbproject/project.properties @@ -12,7 +12,7 @@ build.type=DEVELOPMENT update_versions=false #custom JVM options #Note: can be higher on 64 bit systems, should be in sync with build.xml -run.args.extra=-J-Xms24m -J-Xmx768m -J-XX:MaxPermSize=256M -J-Xverify:none +run.args.extra=-J-Xms24m -J-Xmx512m -J-XX:MaxPermSize=128M -J-Xverify:none auxiliary.org-netbeans-modules-apisupport-installer.license-type=apache.v2 auxiliary.org-netbeans-modules-apisupport-installer.os-linux=false auxiliary.org-netbeans-modules-apisupport-installer.os-macosx=false @@ -30,6 +30,7 @@ modules=\ ${project.org.sleuthkit.autopsy.core}:\ ${project.org.sleuthkit.autopsy.corelibs}:\ ${project.org.sleuthkit.autopsy.sevenzip}:\ + ${project.org.sleuthkit.autopsy.scalpel}:\ ${project.org.sleuthkit.autopsy.timeline} project.org.sleuthkit.autopsy.core=Core project.org.sleuthkit.autopsy.corelibs=CoreLibs @@ -40,5 +41,6 @@ project.org.sleuthkit.autopsy.testing=Testing project.org.sleuthkit.autopsy.thunderbirdparser=thunderbirdparser project.org.sleuthkit.autopsy.exifparser=ExifParser project.org.sleuthkit.autopsy.sevenzip=SevenZip +project.org.sleuthkit.autopsy.scalpel=ScalpelCarver project.org.sleuthkit.autopsy.timeline=Timeline