diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6c1d0d6db1..95919f7988 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -59,7 +59,7 @@ import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess; public class Case implements SleuthkitCase.ErrorObserver { private static final String autopsyVer = Version.getVersion(); // current version of autopsy. Change it when the version is changed - private static final String appName = Version.getName() + " " + autopsyVer; + private static String appName = null; /** * Property name that indicates the name of the current case has changed. * Fired with the case is renamed, and when the current case is @@ -507,6 +507,9 @@ public class Case implements SleuthkitCase.ErrorObserver { * @return appName */ public static String getAppName() { + if ((appName == null ) || appName.equals("")) { + appName = WindowManager.getDefault().getMainWindow().getTitle(); + } return appName; } @@ -575,6 +578,19 @@ public class Case implements SleuthkitCase.ErrorObserver { return xmlcm.getCacheDir(); } } + + /** + * Gets the full path to the export directory of this case + * + * @return export DirectoryPath + */ + public String getExportDirectory() { + if (xmlcm == null) { + return ""; + } else { + return xmlcm.getExportDir(); + } + } /** * get the created date of this case diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 501b1f488e..49c5b313a0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -24,16 +24,14 @@ import java.awt.Dimension; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import javax.swing.ImageIcon; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JPanel; import org.openide.util.Lookup; -import org.sleuthkit.autopsy.coreutils.Version; -import org.netbeans.api.options.OptionsDisplayer; /** * - * @author jantonius */ public class CueBannerPanel extends javax.swing.JPanel { @@ -45,11 +43,19 @@ public class CueBannerPanel extends javax.swing.JPanel { private static JPanel caller = new JPanel(); private String className = this.getClass().toString(); - /** Creates new form CueBannerPanel */ public CueBannerPanel() { initComponents(); } + public CueBannerPanel(String welcomeLogo) { + initComponents(); + ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class); + if (cl != null) { + ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo)); + autopsyLogo.setIcon(icon); + } + } + /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is @@ -254,7 +260,7 @@ public class CueBannerPanel extends javax.swing.JPanel { */ public void setCloseButtonText(String text) { closeButton.setText(text); - } + } /** * Close the open recent cases window. diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java index 8d477b18fa..f100123479 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java @@ -58,7 +58,7 @@ public final class StartupWindow extends JDialog implements StartupWindowInterfa // set the location of the popUp Window on the center of the screen setLocation((screenDimension.width - w) / 2, (screenDimension.height - h) / 2); - + CueBannerPanel welcomeWindow = new CueBannerPanel(); // add the command to close the window to the button on the Volume Detail Panel diff --git a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResultViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResultViewer.java index 0ad466151e..8a4b55e893 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponentinterfaces/DataResultViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java index dfff6f0e83..abd3643c68 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -39,11 +39,10 @@ import org.sleuthkit.autopsy.coreutils.Logger; * Holds commonalities between all DataResultViewers, such as: * - Pushes selection to DataContentViewers */ -public abstract class AbstractDataResultViewer extends JPanel implements - DataResultViewer, Provider { +public abstract class AbstractDataResultViewer extends JPanel implements DataResultViewer, Provider { private static final Logger logger = Logger.getLogger(AbstractDataResultViewer.class.getName()); - protected transient ExplorerManager em = new ExplorerManager(); + protected transient ExplorerManager em; private PropertyChangeListener nodeSelListener; /** * Content viewer to respond to selection events Either the main one, or @@ -51,8 +50,17 @@ public abstract class AbstractDataResultViewer extends JPanel implements */ protected DataContent contentViewer; + public AbstractDataResultViewer(ExplorerManager explorerManager) { + this.em = explorerManager; + initialize(); + } + public AbstractDataResultViewer() { + em = new ExplorerManager(); + initialize(); + } + private void initialize() { //DataContent is designed to return only the default viewer from lookup //use the default one unless set otherwise contentViewer = Lookup.getDefault().lookup(DataContent.class); @@ -113,19 +121,12 @@ public abstract class AbstractDataResultViewer extends JPanel implements } }; - em.addPropertyChangeListener(nodeSelListener); + em.addPropertyChangeListener(nodeSelListener); } - + @Override public void clearComponent() { em.removePropertyChangeListener(nodeSelListener); - - try { - this.em.getRootContext().destroy(); - em = null; - } catch (IOException ex) { - logger.log(Level.WARNING, "Can't clear the component of the Thumbnail Result Viewer.", ex); - } } @Deprecated diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java index c7840a2bd4..ab36ed50c8 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java @@ -177,6 +177,7 @@ public class DataContentViewerMedia extends javax.swing.JPanel implements DataCo @Override public void resetComponent() { + lastFile = null; videoPanel.reset(); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java index 7bd8f5d8e5..9cfd240df6 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultPanel.java @@ -27,6 +27,7 @@ import java.util.logging.Level; import javax.swing.JTabbedPane; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import org.openide.explorer.ExplorerManager; import org.openide.nodes.Node; import org.openide.util.Lookup; import org.sleuthkit.autopsy.casemodule.Case; @@ -47,11 +48,12 @@ import org.sleuthkit.autopsy.coreutils.Logger; */ public class DataResultPanel extends javax.swing.JPanel implements DataResult, ChangeListener { + private ExplorerManager explorerManager; private Node rootNode; private PropertyChangeSupport pcs; // Different DataResultsViewers - private final List viewers = new ArrayList(); + private final List viewers = new ArrayList<>(); //custom content viewer to send selections to, or null if the main one private DataContent customContentViewer; private boolean isMain; @@ -90,7 +92,6 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C this.isMain = isMain; this.title = title; - } /** @@ -110,7 +111,6 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C this.customContentViewer = customContentViewer; } - /** * Factory method to create, customize and open a new custom data result panel. * @@ -170,20 +170,31 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C this.customContentViewer = customContentViewer; } - - /** * Initializes the panel internals and activates it. * Call it within your top component when it is opened. * Do not use if used one of the factory methods to create and open the component. */ public void open() { + if (null == this.explorerManager) { + this.explorerManager = ExplorerManager.find(this); + } + // Add all the DataContentViewer to the tabbed pannel. // (Only when the it's opened at the first time: tabCount = 0) int totalTabs = this.dataResultTabbedPanel.getTabCount(); if (totalTabs == 0) { - // find all dataContentViewer and add them to the tabbed pane + // @@@ Restore the implementation of DataResultViewerTable and DataResultViewerThumbnail + // as DataResultViewer service providers when DataResultViewers can be made compatible with node + // multiple selection actions. + addDataResultViewer(new DataResultViewerTable(this.explorerManager)); + addDataResultViewer(new DataResultViewerThumbnail(this.explorerManager)); + + // Find all DataResultViewer service providers and add them to the tabbed pane. for (DataResultViewer factory : Lookup.getDefault().lookupAll(DataResultViewer.class)) { + // @@@ Revist this isMain condition, it may be obsolete. If not, + // document the intent of DataResultViewer.createInstance() in the + // DataResultViewer interface defintion. DataResultViewer drv; if (isMain) { //for main window, use the instance in the lookup @@ -193,14 +204,7 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C //create a new instance of the viewer for non-main window drv = factory.createInstance(); } - UpdateWrapper resultViewer = new UpdateWrapper(drv); - if (customContentViewer != null) { - //set custom content viewer to respond to events from this result viewer - resultViewer.setContentViewer(customContentViewer); - } - this.viewers.add(resultViewer); - this.dataResultTabbedPanel.addTab(drv.getTitle(), drv.getComponent()); - + addDataResultViewer(drv); } } @@ -211,12 +215,18 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C } } - this.setVisible(true); - - } + private void addDataResultViewer(DataResultViewer dataResultViewer) { + UpdateWrapper viewerWrapper = new UpdateWrapper(dataResultViewer); + if (null != this.customContentViewer) { + viewerWrapper.setContentViewer(this.customContentViewer); + } + this.viewers.add(viewerWrapper); + this.dataResultTabbedPanel.addTab(dataResultViewer.getTitle(), dataResultViewer.getComponent()); + } + /** * Tears down the component. * Use within your outer container (such as a top component) when it goes away to tear @@ -249,12 +259,8 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C this.removeAll(); this.setVisible(false); } - - - } - @Override public synchronized void addPropertyChangeListener(PropertyChangeListener listener) { if (pcs == null) { @@ -335,8 +341,6 @@ public class DataResultPanel extends javax.swing.JPanel implements DataResult, C return ret; } - - public boolean canClose() { return (!this.isMain) || !Case.existsCurrentCase() || Case.getCurrentCase().getRootObjectsCount() == 0; // only allow this window to be closed when there's no case opened or no image in this case } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java index 61560f9e99..971d9addfb 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultTopComponent.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.List; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResult; import java.util.logging.Level; +import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerUtils; import org.openide.util.NbBundle; import org.openide.windows.TopComponent; @@ -50,15 +51,15 @@ import org.sleuthkit.autopsy.coreutils.Logger; * * Implements DataResult interface by delegating to the encapsulated DataResultPanel. */ -public class DataResultTopComponent extends TopComponent implements DataResult { +public class DataResultTopComponent extends TopComponent implements DataResult, ExplorerManager.Provider { private static final Logger logger = Logger.getLogger(DataResultTopComponent.class.getName()); + private ExplorerManager explorerManager = new ExplorerManager(); private DataResultPanel dataResultPanel; //embedded component with all the logic private boolean isMain; - private boolean lookupSet = false; private String customModeName; - //keep track of tcs openeded for menu presenters + //keep track of tcs opened for menu presenters private static final List activeComponentIds = Collections.synchronizedList(new ArrayList()); /** @@ -69,14 +70,10 @@ public class DataResultTopComponent extends TopComponent implements DataResult { * @param title title of the data result window */ public DataResultTopComponent(boolean isMain, String title) { - super(); - - //dataResultPanel is added to this tc using UI builder + associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap())); this.dataResultPanel = new DataResultPanel(isMain, title); - initComponents(); customizeComponent(isMain, title); - } /** @@ -89,18 +86,13 @@ public class DataResultTopComponent extends TopComponent implements DataResult { * to */ DataResultTopComponent(String name, String mode, DataContentTopComponent customContentViewer) { - super(); + associateLookup(ExplorerUtils.createLookup(explorerManager, getActionMap())); this.customModeName = mode; - - //custom content viewer to link to this result viewer - //dataResultPanel is added to this tc using UI builder dataResultPanel = new DataResultPanel(name, customContentViewer); - initComponents(); - customizeComponent(isMain, name);; - + customizeComponent(isMain, name); } - + private void customizeComponent(boolean isMain, String title) { this.isMain = isMain; this.customModeName = null; @@ -185,16 +177,19 @@ public class DataResultTopComponent extends TopComponent implements DataResult { return newDataResult; } + @Override + public ExplorerManager getExplorerManager() { + return explorerManager; + } + /** * Get a list with names of active windows ids, e.g. for the menus * @return */ public static List getActiveComponentIds() { - return new ArrayList(activeComponentIds); + return new ArrayList<>(activeComponentIds); } - - /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -226,7 +221,6 @@ public class DataResultTopComponent extends TopComponent implements DataResult { } else { return TopComponent.PERSISTENCE_ALWAYS; } - } @Override @@ -240,54 +234,36 @@ public class DataResultTopComponent extends TopComponent implements DataResult { return dataResultPanel.getViewers(); } - - private void setCustomMode() { if (customModeName != null) { //putClientProperty("TopComponentAllowDockAnywhere", Boolean.TRUE); Mode mode = WindowManager.getDefault().findMode(customModeName); if (mode != null) { - logger.log(Level.INFO, "Found custom mode, setting: " + customModeName); + StringBuilder message = new StringBuilder("Found custom mode, setting: "); + message.append(customModeName); + logger.log(Level.INFO, message.toString()); mode.dockInto(this); } else { - logger.log(Level.WARNING, "Could not find mode: " + customModeName + ", will dock into the default one"); + StringBuilder message = new StringBuilder("Could not find mode: "); + message.append(customModeName); + message.append(", will dock into the default one"); + logger.log(Level.WARNING, message.toString()); } } - } @Override public void componentOpened() { super.componentOpened(); - - this.dataResultPanel.open(); - - /* @@@ Short-term hack to associate lookup with the table view so that we can do multi-select. - * Longer-term solution is to use same explorer Manager for all viewers. - */ - if (!this.lookupSet) { - List resultViewers = this.dataResultPanel.getViewers(); - for (DataResultViewer viewer : resultViewers) { - if (viewer instanceof DataResultViewerTable) { - associateLookup(ExplorerUtils.createLookup(((DataResultViewerTable)viewer).getExplorerManager(), getActionMap())); - break; - } - } - - this.lookupSet = true; - } + this.dataResultPanel.open(); } - - @Override public void componentClosed() { super.componentClosed(); - activeComponentIds.remove(this.getName()); - dataResultPanel.close(); - + dataResultPanel.close(); } @Override diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 6f5368578b..1b5440036d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import javax.swing.JTable; import javax.swing.ListSelectionModel; import org.netbeans.swing.outline.DefaultOutlineModel; +import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.OutlineView; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; @@ -38,23 +39,39 @@ import org.openide.nodes.Node; import org.openide.nodes.Node.Property; import org.openide.nodes.Node.PropertySet; import org.openide.nodes.Sheet; -import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; /** * DataResult sortable table viewer */ -@ServiceProvider(service = DataResultViewer.class) +// @@@ Restore implementation of DataResultViewerTable as a DataResultViewer +// service provider when DataResultViewers can be made compatible with node +// multiple selection actions. +//@ServiceProvider(service = DataResultViewer.class) public class DataResultViewerTable extends AbstractDataResultViewer { private String firstColumnLabel = "Name"; - private Set propertiesAcc = new LinkedHashSet(); + private Set propertiesAcc = new LinkedHashSet<>(); private static final Logger logger = Logger.getLogger(DataResultViewerTable.class.getName()); /** - * Creates new form DataResultViewerTable + * Creates a DataResultViewerTable object that is compatible with node + * multiple selection actions. + */ + public DataResultViewerTable(ExplorerManager explorerManager) { + super(explorerManager); + initialize(); + } + + /** + * Creates a DataResultViewerTable object that is NOT compatible with node + * multiple selection actions. */ public DataResultViewerTable() { + initialize(); + } + + private void initialize() { initComponents(); OutlineView ov = ((OutlineView) this.tableScrollPanel); @@ -66,9 +83,9 @@ public class DataResultViewerTable extends AbstractDataResultViewer { // don't show the root node ov.getOutline().setRootVisible(false); - ov.getOutline().setDragEnabled(false); + ov.getOutline().setDragEnabled(false); } - + /** * Expand node * @@ -435,8 +452,6 @@ public class DataResultViewerTable extends AbstractDataResultViewer { this.tableScrollPanel.removeAll(); this.tableScrollPanel = null; - //this destroys em super.clearComponent(); - } } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form index 48d26daaa7..14aac889e5 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form @@ -39,6 +39,8 @@ + + @@ -61,6 +63,7 @@ + @@ -196,5 +199,20 @@ + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index f63e4944c8..496afb71c3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -22,6 +22,7 @@ import java.awt.Color; import java.awt.Cursor; import java.awt.EventQueue; import java.beans.PropertyChangeEvent; +import java.util.Arrays; import java.util.logging.Level; import javax.swing.JOptionPane; import org.sleuthkit.autopsy.coreutils.Logger; @@ -29,6 +30,7 @@ import javax.swing.ListSelectionModel; import javax.swing.SwingWorker; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; +import org.openide.explorer.ExplorerManager; import org.openide.explorer.view.IconView; import org.openide.nodes.AbstractNode; import org.openide.nodes.Children; @@ -37,7 +39,6 @@ import org.openide.nodes.NodeEvent; import org.openide.nodes.NodeListener; import org.openide.nodes.NodeMemberEvent; import org.openide.nodes.NodeReorderEvent; -import org.openide.util.lookup.ServiceProvider; import org.sleuthkit.autopsy.corecomponentinterfaces.DataResultViewer; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TskCoreException; @@ -50,7 +51,10 @@ import org.sleuthkit.datamodel.TskCoreException; * are being lazy loaded or not. * */ -@ServiceProvider(service = DataResultViewer.class) +// @@@ Restore implementation of DataResultViewerThumbnail as a DataResultViewer +// service provider when DataResultViewers can be made compatible with node +// multi-selection actions. +//@ServiceProvider(service = DataResultViewer.class) public final class DataResultViewerThumbnail extends AbstractDataResultViewer { private static final Logger logger = Logger.getLogger(DataResultViewerThumbnail.class.getName()); @@ -58,25 +62,37 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { private int curPage; private int totalPages; private int curPageImages; + private int iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; private final PageUpdater pageUpdater = new PageUpdater(); /** - * Creates new form DataResultViewerThumbnail + * Creates a DataResultViewerThumbnail object that is compatible with node + * multiple selection actions. + */ + public DataResultViewerThumbnail(ExplorerManager explorerManager) { + super(explorerManager); + initialize(); + } + + /** + * Creates a DataResultViewerThumbnail object that is NOT compatible with + * node multiple selection actions. */ public DataResultViewerThumbnail() { - super(); - + initialize(); + } + + private void initialize() { initComponents(); // only allow one item to be selected at a time - ((IconView) thumbnailScrollPanel).setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + ((IconView) thumbnailScrollPanel).setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); curPage = -1; totalPages = 0; curPageImages = 0; - - } - + } + /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always @@ -97,6 +113,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { filePathLabel = new javax.swing.JLabel(); goToPageLabel = new javax.swing.JLabel(); goToPageField = new javax.swing.JTextField(); + thumbnailSizeComboBox = new javax.swing.JComboBox(); thumbnailScrollPanel.setPreferredSize(new java.awt.Dimension(582, 348)); @@ -146,6 +163,14 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { } }); + thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Small Thumbnails", "Medium Thumbnails", "Large Thumbnails" })); + thumbnailSizeComboBox.setSelectedIndex(1); + thumbnailSizeComboBox.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + thumbnailSizeComboBoxActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -172,8 +197,10 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { .addGap(12, 12, 12) .addComponent(imagesLabel) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE))) - .addContainerGap()) + .addComponent(imagesRangeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -189,7 +216,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { .addComponent(imagesLabel) .addComponent(imagesRangeLabel) .addComponent(goToPageLabel) - .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addComponent(goToPageField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(thumbnailSizeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) .addGap(0, 0, 0) .addComponent(thumbnailScrollPanel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) @@ -209,6 +237,38 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { goToPage(goToPageField.getText()); }//GEN-LAST:event_goToPageFieldActionPerformed + private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thumbnailSizeComboBoxActionPerformed + + iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; //default size + switch(thumbnailSizeComboBox.getSelectedIndex()) { + case 0: + iconSize = ThumbnailViewNode.ICON_SIZE_SMALL; + break; + case 2: + iconSize = ThumbnailViewNode.ICON_SIZE_LARGE; + break; + } + + Node root = em.getRootContext(); + for (Children c : Arrays.asList(root.getChildren()) ) { + ((ThumbnailViewChildren)c).setIconSize(iconSize); + } + + for (Node page : root.getChildren().getNodes()) { + for (Node node : page.getChildren().getNodes()) { + ((ThumbnailViewNode)node).setIconSize(iconSize); + } + } + + // Temporarily set the explored context to the root, instead of a child node. + // This is a workaround hack to convince org.openide.explorer.ExplorerManager to + // update even though the new and old Node values are identical. This in turn + // will cause the entire view to update completely. After this we + // immediately set the node back to the current child by calling switchPage(). + em.setExploredContext(root); + switchPage(); + }//GEN-LAST:event_thumbnailSizeComboBoxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel filePathLabel; private javax.swing.JTextField goToPageField; @@ -221,6 +281,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { private javax.swing.JButton pagePrevButton; private javax.swing.JLabel pagesLabel; private javax.swing.JScrollPane thumbnailScrollPanel; + private javax.swing.JComboBox thumbnailSizeComboBox; // End of variables declaration//GEN-END:variables @Override @@ -246,8 +307,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { if (givenNode != null) { - ThumbnailViewChildren childNode = new ThumbnailViewChildren(givenNode); - + ThumbnailViewChildren childNode = new ThumbnailViewChildren(givenNode, iconSize); + final Node root = new AbstractNode(childNode); pageUpdater.setRoot(root); root.addNodeListener(pageUpdater); @@ -315,7 +376,6 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { this.thumbnailScrollPanel.removeAll(); this.thumbnailScrollPanel = null; - //this destroyes em super.clearComponent(); } @@ -377,7 +437,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { progress.start(); progress.switchToIndeterminate(); Node root = em.getRootContext(); - Node pageNode = root.getChildren().getNodeAt(curPage - 1); + Node pageNode = root.getChildren().getNodeAt(curPage - 1); em.setExploredContext(pageNode); curPageImages = pageNode.getChildren().getNodesCount(); return null; @@ -387,8 +447,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { protected void done() { progress.finish(); setCursor(null); - updateControls(); - + updateControls(); } }.execute(); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.form b/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.form index e37b43cc05..d529361ded 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.form @@ -21,16 +21,19 @@ - + + - - - - + + + + + + @@ -43,17 +46,15 @@ - + - + - - - - - - - + + + + + @@ -80,26 +81,6 @@ - - - - - - - - - - - - - - - - - - - - @@ -159,5 +140,18 @@ + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.java index 20c1508000..0499404c42 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ProductInformationPanel.java @@ -43,13 +43,13 @@ import org.sleuthkit.datamodel.SleuthkitJNI; /** * Custom "About" window panel. */ -class ProductInformationPanel extends JPanel implements HyperlinkListener { +public class ProductInformationPanel extends JPanel implements HyperlinkListener { private URL url = null; private Icon about; private boolean verboseLogging; - ProductInformationPanel() { + public ProductInformationPanel() { about = new ImageIcon(org.netbeans.core.startup.Splash.loadContent(true)); initComponents(); jLabel1.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); @@ -67,16 +67,15 @@ class ProductInformationPanel extends JPanel implements HyperlinkListener { // //GEN-BEGIN:initComponents private void initComponents() { - java.awt.GridBagConstraints gridBagConstraints; jLabel1 = new javax.swing.JLabel(); jPanel1 = new javax.swing.JPanel(); - jButton2 = new javax.swing.JButton(); jScrollPane3 = new javax.swing.JScrollPane(); copyright = new javax.swing.JTextPane(); jScrollPane2 = new javax.swing.JScrollPane(); description = new javax.swing.JTextPane(); verboseLoggingButton = new javax.swing.JButton(); + jButton2 = new javax.swing.JButton(); setBackground(new java.awt.Color(255, 255, 255)); @@ -92,22 +91,10 @@ class ProductInformationPanel extends JPanel implements HyperlinkListener { jPanel1.setBackground(new java.awt.Color(255, 255, 255)); jPanel1.setLayout(new java.awt.GridBagLayout()); - jButton2.setBackground(new java.awt.Color(255, 255, 255)); - jButton2.setText(NbBundle.getMessage(ProductInformationPanel.class, "LBL_Close")); // NOI18N - jButton2.addActionListener(new java.awt.event.ActionListener() { - public void actionPerformed(java.awt.event.ActionEvent evt) { - jButton2ActionPerformed(evt); - } - }); - gridBagConstraints = new java.awt.GridBagConstraints(); - gridBagConstraints.weightx = 1.0; - gridBagConstraints.weighty = 1.0; - jPanel1.add(jButton2, gridBagConstraints); - jScrollPane3.setBorder(null); copyright.setBorder(null); - copyright.setContentType("text/html"); + copyright.setContentType("text/html"); // NOI18N copyright.setEditable(false); copyright.setText(org.openide.util.NbBundle.getBundle(ProductInformationPanel.class).getString("LBL_Copyright")); // NOI18N copyright.addMouseListener(new java.awt.event.MouseAdapter() { @@ -117,7 +104,7 @@ class ProductInformationPanel extends JPanel implements HyperlinkListener { }); jScrollPane3.setViewportView(copyright); - description.setContentType("text/html"); + description.setContentType("text/html"); // NOI18N description.setEditable(false); jScrollPane2.setViewportView(description); @@ -129,6 +116,14 @@ class ProductInformationPanel extends JPanel implements HyperlinkListener { } }); + jButton2.setBackground(new java.awt.Color(255, 255, 255)); + jButton2.setText(NbBundle.getMessage(ProductInformationPanel.class, "LBL_Close")); // NOI18N + jButton2.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton2ActionPerformed(evt); + } + }); + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -136,13 +131,15 @@ class ProductInformationPanel extends JPanel implements HyperlinkListener { .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) .addComponent(jScrollPane3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) .addComponent(jLabel1, javax.swing.GroupLayout.DEFAULT_SIZE, 394, Short.MAX_VALUE) - .addGroup(layout.createSequentialGroup() - .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 237, Short.MAX_VALUE) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(verboseLoggingButton))) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(verboseLoggingButton, javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jButton2, javax.swing.GroupLayout.Alignment.TRAILING)))) .addContainerGap()) ); layout.setVerticalGroup( @@ -151,15 +148,15 @@ class ProductInformationPanel extends JPanel implements HyperlinkListener { .addContainerGap() .addComponent(jLabel1) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) - .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 101, Short.MAX_VALUE) + .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 94, Short.MAX_VALUE) .addGap(32, 32, 32) - .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 103, Short.MAX_VALUE) + .addComponent(jScrollPane2, javax.swing.GroupLayout.DEFAULT_SIZE, 96, Short.MAX_VALUE) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addGap(27, 27, 27) - .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) - .addComponent(verboseLoggingButton)) + .addComponent(verboseLoggingButton) + .addGap(0, 0, 0) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(18, 18, 18) + .addComponent(jButton2) .addContainerGap()) ); }// //GEN-END:initComponents @@ -253,7 +250,11 @@ private void jLabel1MouseClicked(java.awt.event.MouseEvent evt) {//GEN-FIRST:eve private static String getEncodingValue() { return System.getProperty("file.encoding", "unknown"); } - + + public void setCopyright(String text) { + copyright.setText(text); + } + @Override public void hyperlinkUpdate(HyperlinkEvent event) { if (HyperlinkEvent.EventType.ENTERED == event.getEventType()) { diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java index 3ad547d12a..7c4284cbf3 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewChildren.java @@ -52,15 +52,17 @@ class ThumbnailViewChildren extends Children.Keys { private final HashMap> pages = new HashMap>(); private int totalImages = 0; private int totalPages = 0; + private int iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; private static final Logger logger = Logger.getLogger(ThumbnailViewChildren.class.getName()); /** * the constructor */ - ThumbnailViewChildren(Node arg) { + ThumbnailViewChildren(Node arg, int iconSize) { super(true); //support lazy loading this.parent = arg; + this.iconSize = iconSize; // } @@ -153,6 +155,10 @@ class ThumbnailViewChildren extends Children.Keys { return false; } + public void setIconSize(int iconSize) { + this.iconSize = iconSize; + } + private static class IsSupportedContentVisitor extends ContentVisitor.Default { private final List SUPP_EXTENSIONS; @@ -255,7 +261,7 @@ class ThumbnailViewChildren extends Children.Keys { @Override protected Node[] createNodes(Node wrapped) { if (wrapped != null) { - final ThumbnailViewNode thumb = new ThumbnailViewNode(wrapped); + final ThumbnailViewNode thumb = new ThumbnailViewNode(wrapped, iconSize); return new Node[]{thumb}; } else { return new Node[]{}; diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java index ef562ae0c4..b69c7db3f5 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -49,16 +49,21 @@ import org.sleuthkit.datamodel.TskException; */ class ThumbnailViewNode extends FilterNode { - private SoftReference iconCache; + private SoftReference iconCache = null; private static final Image defaultIcon = new ImageIcon("/org/sleuthkit/autopsy/images/file-icon.png").getImage(); private static final Logger logger = Logger.getLogger(ThumbnailViewNode.class.getName()); + static final int ICON_SIZE_SMALL = 50; + static final int ICON_SIZE_MEDIUM = 100; + static final int ICON_SIZE_LARGE = 200; + private int iconSize = ICON_SIZE_MEDIUM; //private final BufferedImage defaultIconBI; /** * the constructor */ - ThumbnailViewNode(Node arg) { + ThumbnailViewNode(Node arg, int iconSize) { super(arg, Children.LEAF); + this.iconSize = iconSize; } @Override @@ -73,36 +78,31 @@ class ThumbnailViewNode extends FilterNode { @Override public Image getIcon(int type) { Image icon = null; - + if (iconCache != null) { icon = iconCache.get(); } - if (icon == null) { Content content = this.getLookup().lookup(Content.class); if (content != null) { + // If a thumbnail file is already saved locally if (getFile(content.getId()).exists()) { try { - icon = ImageIO.read(getFile(content.getId())); - if (icon == null) { + BufferedImage bicon = ImageIO.read(getFile(content.getId())); + if (bicon == null) { icon = ThumbnailViewNode.defaultIcon; + } else if (bicon.getWidth() != iconSize) { + icon = generateAndSaveIcon(content); + } else { + icon = bicon; } } catch (IOException ex) { icon = ThumbnailViewNode.defaultIcon; } - } else { - try { - icon = generateIcon(content); - if (icon == null) { - icon = ThumbnailViewNode.defaultIcon; - } else { - ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId())); - } - } catch (IOException ex) { - logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex); - } + } else { // Make a new icon + icon = generateAndSaveIcon(content); } } else { icon = ThumbnailViewNode.defaultIcon; @@ -110,14 +110,33 @@ class ThumbnailViewNode extends FilterNode { iconCache = new SoftReference(icon); } - + return icon; } + private Image generateAndSaveIcon(Content content) { + Image icon = null; + try { + icon = generateIcon(content); + if (icon == null) { + icon = ThumbnailViewNode.defaultIcon; + } else { + File f = getFile(content.getId()); + if (f.exists()) { + f.delete(); + } + ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId())); + } + } catch (IOException ex) { + logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex); + } + return icon; + } + /* * Generate a scaled image */ - static private BufferedImage generateIcon(Content content) { + private BufferedImage generateIcon(Content content) { InputStream inputStream = null; try { @@ -127,7 +146,8 @@ class ThumbnailViewNode extends FilterNode { logger.log(Level.WARNING, "No image reader for file: " + content.getName()); return null; } - BufferedImage biScaled = ScalrWrapper.resizeFast(bi, 100, 100); + BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconSize); + return biScaled; }catch (OutOfMemoryError e) { logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e); @@ -151,4 +171,10 @@ class ThumbnailViewNode extends FilterNode { private static File getFile(long id) { return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".jpg"); } + + public void setIconSize(int iconSize) { + this.iconSize = iconSize; + iconCache = null; + } + } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java index 66c0cd2bb8..cb2b6d0965 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/FileSize.java @@ -40,6 +40,7 @@ import org.sleuthkit.datamodel.LayoutFile; import org.sleuthkit.datamodel.LocalFile; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; +import org.sleuthkit.datamodel.TskData; import org.sleuthkit.datamodel.VirtualDirectory; /** @@ -224,30 +225,34 @@ public class FileSize implements AutopsyVisitableItem { @Override protected boolean createKeys(List list) { - list.addAll(runFsQuery()); + List l = runFsQuery(); + if (l == null) { + return false; + } + list.addAll(l); return true; } private String makeQuery() { - String query = ""; + String query; switch (filter) { case SIZE_50_200: - query = "size >= 50000000 AND size < 200000000"; - + query = "(size >= 50000000 AND size < 200000000)"; break; case SIZE_200_1000: - query = "size >= 200000000 AND size < 1000000000"; - + query = "(size >= 200000000 AND size < 1000000000)"; break; case SIZE_1000_: - query = "size >= 1000000000"; + query = "(size >= 1000000000)"; break; default: logger.log(Level.SEVERE, "Unsupported filter type to get files by size: " + filter); - + return null; } + // ignore unalloc block files + query = query + " AND (type != " + TskData.TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType() + ")"; return query; } @@ -256,6 +261,10 @@ public class FileSize implements AutopsyVisitableItem { List ret = new ArrayList(); String query = makeQuery(); + if (query == null) { + return null; + } + try { ret = skCase.findAllFilesWhere(query); } catch (TskCoreException e) { diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java index 8a69be7af1..11ad9d6498 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/Tags.java @@ -80,25 +80,20 @@ public class Tags implements AutopsyVisitableItem { // When this class is loaded, either create an new app settings file or // get the tag names setting from the existing app settings file. static { - if (!ModuleSettings.configExists(APP_SETTINGS_FILE_NAME)) { - ModuleSettings.makeConfigFile(APP_SETTINGS_FILE_NAME); - } - else { - String setting = ModuleSettings.getConfigSetting(APP_SETTINGS_FILE_NAME, TAG_NAMES_SETTING_KEY); - if (!setting.isEmpty()) { - // Make a speedy lookup for the tag names in the setting to aid in the - // detection of new tag names. - List tagNamesFromAppSettings = Arrays.asList(setting.split(",")); - for (String tagName : tagNamesFromAppSettings) { - appSettingTagNames.add(tagName); - } - - // Load the raw comma separated values list from the setting into a - // string builder to facilitate adding new tag names to the list and writing - // it back to the app settings file. - tagNamesAppSetting.append(setting); - } - } + String setting = ModuleSettings.getConfigSetting(APP_SETTINGS_FILE_NAME, TAG_NAMES_SETTING_KEY); + if (null != setting && !setting.isEmpty()) { + // Make a speedy lookup for the tag names in the setting to aid in the + // detection of new tag names. + List tagNamesFromAppSettings = Arrays.asList(setting.split(",")); + for (String tagName : tagNamesFromAppSettings) { + appSettingTagNames.add(tagName); + } + + // Load the raw comma separated values list from the setting into a + // string builder to facilitate adding new tag names to the list and writing + // it back to the app settings file. + tagNamesAppSetting.append(setting); + } } Tags(SleuthkitCase skCase) { diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java index e30e9b56b1..ed0ffc23df 100755 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DataResultFilterNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011 Basis Technology Corp. + * Copyright 2011-2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -86,7 +86,9 @@ public class DataResultFilterNode extends FilterNode { private final DisplayableItemNodeVisitor getPreferredActionsDIV; /** - * the constructor + * + * @param node Root node to be passed to DataResult viewers + * @param em ExplorerManager for component that is creating the node */ public DataResultFilterNode(Node node, ExplorerManager em) { super(node, new DataResultFilterChildren(node, em)); @@ -316,6 +318,9 @@ public class DataResultFilterNode extends FilterNode { } } + /* + * Action for double-click / preferred action on nodes. + */ private class GetPreferredActionsDisplayableItemNodeVisitor extends DisplayableItemNodeVisitor.Default { @Override @@ -412,9 +417,11 @@ public class DataResultFilterNode extends FilterNode { public AbstractAction visit(DirectoryNode dn) { if (dn.getDisplayName().equals(DirectoryNode.DOTDOTDIR)) { return openParent(dn); - } else if (!dn.getDisplayName().equals(DirectoryNode.DOTDIR)) { + } + else if (dn.getDisplayName().equals(DirectoryNode.DOTDIR) == false) { return openChild(dn); - } else { + } + else { return null; } } @@ -428,7 +435,8 @@ public class DataResultFilterNode extends FilterNode { public AbstractAction visit(FileNode fn) { if (fn.hasContentChildren()) { return openChild(fn); - } else { + } + else { return null; } } @@ -437,7 +445,8 @@ public class DataResultFilterNode extends FilterNode { public AbstractAction visit(LocalFileNode dfn) { if (dfn.hasContentChildren()) { return openChild(dfn); - } else { + } + else { return null; } } @@ -472,21 +481,31 @@ public class DataResultFilterNode extends FilterNode { return null; } + /** + * Tell the originating ExplorerManager to display the given node. + * @param node Original (non-filtered) node to open + * @return + */ private AbstractAction openChild(AbstractNode node) { - final Node[] parentNode = sourceEm.getSelectedNodes(); - final Node parentContext = parentNode[0]; - final Node original = node; + // get the parent node from sourceEm because that will get us the filtered version of it. + // node.getParentNode() returns the low-level datamodel node. + final Node[] parentFilterNodes = sourceEm.getSelectedNodes(); + final Node parentFilterNode = parentFilterNodes[0]; + final Node originalNode = node; return new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { - if (parentContext != null) { - final int childrenNodesCount = parentContext.getChildren().getNodesCount(); + if (parentFilterNode != null) { + + // Find the filter version of the passed in node. + final int childrenNodesCount = parentFilterNode.getChildren().getNodesCount(); for (int i = 0; i < childrenNodesCount; i++) { - Node selectedNode = parentContext.getChildren().getNodeAt(i); - if (selectedNode != null && selectedNode.getName().equals(original.getName())) { + Node childFilterNode = parentFilterNode.getChildren().getNodeAt(i); + if (childFilterNode != null && childFilterNode.getName().equals(originalNode.getName())) { try { - sourceEm.setExploredContextAndSelection(selectedNode, new Node[]{selectedNode}); + sourceEm.setExploredContextAndSelection(childFilterNode, new Node[]{childFilterNode}); + break; } catch (PropertyVetoException ex) { // throw an error here Logger logger = Logger.getLogger(DataResultFilterNode.class.getName()); @@ -499,10 +518,16 @@ public class DataResultFilterNode extends FilterNode { }; } + /** + * Tell the originating ExplorerManager to display the parent of the given node. + * @param node Original (non-filtered) node to open + * @return + */ private AbstractAction openParent(AbstractNode node) { - Node[] selectedNode = sourceEm.getSelectedNodes(); - Node selectedContext = selectedNode[0]; - final Node parentNode = selectedContext.getParentNode(); + // @@@ Why do we ignore node? + Node[] selectedFilterNodes = sourceEm.getSelectedNodes(); + Node selectedFilterNode = selectedFilterNodes[0]; + final Node parentNode = selectedFilterNode.getParentNode(); return new AbstractAction() { @Override diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java index 23e18ea4fa..0c7c2ef543 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/DirectoryTreeTopComponent.java @@ -609,14 +609,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat //and legacy selection events are pumped return; } - //this looks redundant? -// if (getSelectedNode() == null && oldNodes != null) { -// try { -// em.setSelectedNodes(oldNodes); -// } catch (PropertyVetoException ex) { -// logger.log(Level.WARNING, "Error resetting node", ex); -// } -// } + // Some lock that prevents certain Node operations is set during the // ExplorerManager selection-change, so we must handle changes after the @@ -640,26 +633,24 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat return; } Node originNode = origin.getNode(); - - DirectoryTreeTopComponent.this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); + //set node, wrap in filter node first to filter out children Node drfn = new DataResultFilterNode(originNode, DirectoryTreeTopComponent.this.em); - DirectoryTreeTopComponent.this.dataResult.setNode(new TableFilterNode(drfn, true)); + dataResult.setNode(new TableFilterNode(drfn, true)); String displayName = ""; - if (originNode.getLookup().lookup(Content.class) != null) { - Content content = originNode.getLookup().lookup(Content.class); - if (content != null) { - try { - displayName = content.getUniquePath(); - } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); - } - } - } else if (originNode.getLookup().lookup(String.class) != null) { + Content content = originNode.getLookup().lookup(Content.class); + if (content != null) { + try { + displayName = content.getUniquePath(); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Exception while calling Content.getUniquePath() for node: " + originNode); + } + } + else if (originNode.getLookup().lookup(String.class) != null) { displayName = originNode.getLookup().lookup(String.class); } - DirectoryTreeTopComponent.this.dataResult.setPath(displayName); + dataResult.setPath(displayName); } // set the directory listing to be active @@ -674,7 +665,7 @@ public final class DirectoryTreeTopComponent extends TopComponent implements Dat } } } finally { - DirectoryTreeTopComponent.this.setCursor(null); + setCursor(null); } } }); diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java index 1442cb57cd..d645441fbc 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java @@ -21,7 +21,9 @@ package org.sleuthkit.autopsy.directorytree; import java.awt.Component; import java.awt.event.ActionEvent; import java.io.File; +import java.util.ArrayList; import java.util.Collection; +import java.util.Iterator; import java.util.concurrent.CancellationException; import java.util.logging.Level; import org.sleuthkit.autopsy.coreutils.Logger; @@ -34,13 +36,16 @@ import org.netbeans.api.progress.ProgressHandleFactory; import org.openide.util.Cancellable; import org.openide.util.Utilities; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.coreutils.FileUtil; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; import org.sleuthkit.autopsy.datamodel.ContentUtils.ExtractFscContentVisitor; import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.autopsy.coreutils.FileUtil; +import org.sleuthkit.autopsy.datamodel.ContentUtils; +import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.TskCoreException; /** - * Exports files and folders + * Extracts AbstractFiles to a location selected by the user. */ public final class ExtractAction extends AbstractAction { private Logger logger = Logger.getLogger(ExtractAction.class.getName()); @@ -54,143 +59,206 @@ public final class ExtractAction extends AbstractAction { if (null == instance) { instance = new ExtractAction(); } - return instance; } private ExtractAction() { - super("Extract"); + super("Extract File(s)"); } /** - * Asks user to choose destination, then extracts content/directory to - * destination (recursing on directories) - * @param e the action event + * Asks user to choose destination, then extracts content to destination + * (recursing on directories). + * @param e The action event. */ @Override public void actionPerformed(ActionEvent e) { Collection selectedFiles = Utilities.actionsGlobalContext().lookupAll(AbstractFile.class); - for (AbstractFile file : selectedFiles) { - extractFile(e, file); - } + if (selectedFiles.size() > 1) { + extractFiles(e, selectedFiles); + } + else if (selectedFiles.size() == 1) { + AbstractFile source = selectedFiles.iterator().next(); + if (source.isDir()) { + extractFiles(e, selectedFiles); + } + else { + extractFile(e, selectedFiles.iterator().next()); + } + } } - private void extractFile(ActionEvent e, AbstractFile file) { - // Get content and check that it's okay to overwrite existing content - JFileChooser fc = new JFileChooser(); - fc.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory())); - fc.setSelectedFile(new File(file.getName())); - int returnValue = fc.showSaveDialog((Component) e.getSource()); - - if (returnValue == JFileChooser.APPROVE_OPTION) { - File destination = fc.getSelectedFile(); - - // do the check - if (destination.exists()) { - int choice = JOptionPane.showConfirmDialog( - (Component) e.getSource(), - "Destination file already exists, it will be overwritten.", - "Destination already exists!", - JOptionPane.OK_CANCEL_OPTION); - - if (choice != JOptionPane.OK_OPTION) { - return; // Just exit the function - } - - if (!destination.delete()) { - JOptionPane.showMessageDialog( - (Component) e.getSource(), - "Couldn't delete existing file."); - } - } - - try { - ExtractFileThread extract = new ExtractFileThread(); - extract.init(file, e, destination); - extract.execute(); - } catch (Exception ex) { - logger.log(Level.WARNING, "Unable to start background thread.", ex); - } + private void extractFile(ActionEvent e, AbstractFile source) { + JFileChooser fileChooser = new JFileChooser(); + fileChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory())); + fileChooser.setSelectedFile(new File(source.getName())); + if (fileChooser.showSaveDialog((Component)e.getSource()) == JFileChooser.APPROVE_OPTION) { + ArrayList fileExtractionTasks = new ArrayList<>(); + fileExtractionTasks.add(new FileExtractionTask(source, fileChooser.getSelectedFile())); + doFileExtraction(e, fileExtractionTasks); } } - - private class ExtractFileThread extends SwingWorker { - private Logger logger = Logger.getLogger(ExtractFileThread.class.getName()); - private ProgressHandle progress; - private AbstractFile fsContent; - private ActionEvent e; - private File destination; - private void init(AbstractFile fsContent, ActionEvent e, File destination) { - this.fsContent = fsContent; - this.e = e; - this.destination = destination; + private void extractFiles(ActionEvent e, Collection selectedFiles) { + JFileChooser folderChooser = new JFileChooser(); + folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + folderChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory())); + if (folderChooser.showSaveDialog((Component)e.getSource()) == JFileChooser.APPROVE_OPTION) { + File destinationFolder = folderChooser.getSelectedFile(); + if (!destinationFolder.exists()) { + try { + destinationFolder.mkdirs(); + } + catch (Exception ex) { + JOptionPane.showMessageDialog((Component) e.getSource(), "Couldn't create selected folder."); + logger.log(Level.INFO, "Unable to create folder(s) for user " + destinationFolder.getAbsolutePath(), ex); + return; + } + } + + ArrayList fileExtractionTasks = new ArrayList<>(); + for (AbstractFile source : selectedFiles) { + fileExtractionTasks.add(new FileExtractionTask(source, new File(destinationFolder, source.getId() + "-" + source.getName()))); + } + doFileExtraction(e, fileExtractionTasks); + } + } + + private void doFileExtraction(ActionEvent e, ArrayList fileExtractionTasks) { + + // verify all of the sources and destinations are OK + for (Iterator it = fileExtractionTasks.iterator(); it.hasNext(); ) { + FileExtractionTask task = it.next(); + + if (ContentUtils.isDotDirectory(task.source)) { + //JOptionPane.showMessageDialog((Component) e.getSource(), "Cannot extract virtual " + task.source.getName() + " directory.", "File is Virtual Directory", JOptionPane.WARNING_MESSAGE); + it.remove(); + continue; + } + + /* + * @@@ Problems with this code: + * - does not prevent us from having multiple files with the same target name in the task list (in which case, the first ones are overwritten) + * Unique Id was added to set of names before calling this method to deal with that. + */ + if (task.destination.exists()) { + if (JOptionPane.showConfirmDialog((Component) e.getSource(), "Destination file " + task.destination.getAbsolutePath() + " already exists, overwrite?", "File Exists", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) { + if (!FileUtil.deleteFileDir(task.destination)) { + JOptionPane.showMessageDialog((Component) e.getSource(), "Couldn't overwrite existing file " + task.destination.getAbsolutePath()); + it.remove(); + } + } + else { + it.remove(); + } + } } + if (!fileExtractionTasks.isEmpty()) { + try { + FileExtracter extracter = new FileExtracter(fileExtractionTasks); + extracter.execute(); + } + catch (Exception ex) { + logger.log(Level.WARNING, "Unable to start background file extraction thread", ex); + } + } + else { + MessageNotifyUtil.Message.info("No file(s) to extract."); + } + } + + private class FileExtractionTask { + AbstractFile source; + File destination; + + FileExtractionTask(AbstractFile source, File destination) { + this.source = source; + this.destination = destination; + } + } + + private class FileExtracter extends SwingWorker { + private Logger logger = Logger.getLogger(FileExtracter.class.getName()); + private ProgressHandle progress; + private ArrayList extractionTasks; + + FileExtracter(ArrayList extractionTasks) { + this.extractionTasks = extractionTasks; + } + @Override protected Object doInBackground() throws Exception { - logger.log(Level.INFO, "Starting background processing for file extraction."); + if (extractionTasks.isEmpty()) { + return null; + } - // Setup progress bar + // Setup progress bar. final String displayName = "Extracting"; progress = ProgressHandleFactory.createHandle(displayName, new Cancellable() { @Override public boolean cancel() { if (progress != null) progress.setDisplayName(displayName + " (Cancelling...)"); - return ExtractAction.ExtractFileThread.this.cancel(true); + return ExtractAction.FileExtracter.this.cancel(true); } }); - - // Start the progress bar as indeterminate progress.start(); progress.switchToIndeterminate(); - if(fsContent.isFile()) { - // Max content size of 200GB - //long filesize = fsContent.getSize(); - //int unit = (int) (filesize / 100); - progress.switchToDeterminate(100); - } else if(fsContent.isDir()) { - // If dir base progress off number of children - int toProcess = fsContent.getChildren().size(); - progress.switchToDeterminate(toProcess); + + /* @@@ Add back in -> Causes exceptions + int workUnits = 0; + for (FileExtractionTask task : extractionTasks) { + workUnits += calculateProgressBarWorkUnits(task.source); } - - // Start extracting the content/directory - ExtractFscContentVisitor.extract(fsContent, destination, progress, this); - logger.log(Level.INFO, "Done background processing"); + progress.switchToDeterminate(workUnits); + */ + + // Do the extraction tasks. + for (FileExtractionTask task : this.extractionTasks) { + // @@@ Note, we are no longer passing in progress + ExtractFscContentVisitor.extract(task.source, task.destination, null, this); + } + return null; } @Override protected void done() { try { - super.get(); //block and get all exceptions thrown while doInBackground() - } catch (CancellationException ex) { - logger.log(Level.INFO, "Extraction was canceled."); - } catch (InterruptedException ex) { - logger.log(Level.INFO, "Extraction was interrupted."); - } catch (Exception ex) { - logger.log(Level.SEVERE, "Fatal error during file extraction.", ex); - } finally { + super.get(); + } + catch (CancellationException | InterruptedException ex) { + } + catch (Exception ex) { + logger.log(Level.SEVERE, "Fatal error during file extraction", ex); + } + finally { progress.finish(); if (!this.isCancelled()) { - logger.log(Level.INFO, "Extracting completed without cancellation."); - // Alert the user extraction is over - if(fsContent.isDir()) { - MessageNotifyUtil.Message.info("Directory extracted."); - } else if(fsContent.isFile()){ - MessageNotifyUtil.Message.info("File extracted."); - } - } else { - logger.log(Level.INFO, "Attempting to delete file(s)."); - if(FileUtil.deleteFileDir(destination)) { - logger.log(Level.INFO, "Finished deletion sucessfully."); - } else { - logger.log(Level.WARNING, "Deletion attempt complete; not all files were sucessfully deleted."); + MessageNotifyUtil.Message.info("File(s) extracted."); + } + } + } + + private int calculateProgressBarWorkUnits(AbstractFile file) { + int workUnits = 0; + if (file.isFile()) { + workUnits += file.getSize(); + } + else { + try { + for (Content child : file.getChildren()) { + if (child instanceof AbstractFile) { + workUnits += calculateProgressBarWorkUnits((AbstractFile)child); + } } } + catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Could not get children of content", ex); + } } + return workUnits; } } } diff --git a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java index 6597eadc9d..5c7a504af1 100644 --- a/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java +++ b/Core/src/org/sleuthkit/autopsy/ingest/IngestModuleLoader.java @@ -333,7 +333,7 @@ public final class IngestModuleLoader { try { urls.add(new URL(urlPath)); - logger.log(Level.INFO, "JAR: " + urlPath); + //logger.log(Level.INFO, "JAR: " + urlPath); } catch (MalformedURLException ex) { logger.log(Level.WARNING, "Invalid URL: " + urlPath, ex); } @@ -476,13 +476,14 @@ public final class IngestModuleLoader { for (final ModuleInfo moduleInfo : moduleInfos) { if (moduleInfo.isEnabled()) { String basePackageName = moduleInfo.getCodeNameBase(); + + // skip the standard ones if (basePackageName.startsWith("org.netbeans") || basePackageName.startsWith("org.openide")) { - //skip continue; } - logger.log(Level.INFO, "Module enabled: " + moduleInfo.getDisplayName() + " " + basePackageName + logger.log(Level.INFO, "Found module: " + moduleInfo.getDisplayName() + " " + basePackageName + " Build version: " + moduleInfo.getBuildVersion() + " Spec version: " + moduleInfo.getSpecificationVersion() + " Impl version: " + moduleInfo.getImplementationVersion()); @@ -493,6 +494,12 @@ public final class IngestModuleLoader { cb.setScanners(new SubTypesScanner(), new ResourcesScanner()); reflectionsSet.add(new Reflections(cb)); } + else { + // log if we have our own modules disabled + if (moduleInfo.getCodeNameBase().startsWith("org.sleuthkit")) { + logger.log(Level.WARNING, "Sleuth Kit Module not enabled: " + moduleInfo.getDisplayName()); + } + } } /* This area is used to load the example modules. They are not found via lookup since they @@ -520,6 +527,11 @@ public final class IngestModuleLoader { while (it.hasNext()) { logger.log(Level.INFO, "Found DataSource ingest module in: " + reflections.getClass().getSimpleName() + ": " + it.next().toString()); } + + if ((fileModules.isEmpty()) && (dataSourceModules.isEmpty())) { + logger.log(Level.INFO, "Module has no ingest modules: " + reflections.getClass().getSimpleName()); + continue; + } //find out which modules to add //TODO check which modules to remove (which modules were uninstalled) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index 898095757b..c7ca56c678 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2012 Basis Technology Corp. + * Copyright 2013 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -84,12 +84,13 @@ public class ReportGenerator { static final String REPORTS_DIR = "Reports"; ReportGenerator(Map tableModuleStates, Map generalModuleStates) { - // Setup the reporting directory to be [CASE DIRECTORY]/Reports/[Case name] [Timestamp]/ + // Create the root reports directory path of the form: /Reports/ / DateFormat dateFormat = new SimpleDateFormat("MM-dd-yyyy-HH-mm-ss"); Date date = new Date(); - String datenotime = dateFormat.format(date); - this.reportPath = currentCase.getCaseDirectory() + File.separator + REPORTS_DIR + File.separator + currentCase.getName() + " " + datenotime + File.separator; - // Create the reporting directory + String dateNoTime = dateFormat.format(date); + this.reportPath = currentCase.getCaseDirectory() + File.separator + REPORTS_DIR + File.separator + currentCase.getName() + " " + dateNoTime + File.separator; + + // Create the root reports directory. try { FileUtil.createFolder(new File(this.reportPath)); } catch (IOException ex) { @@ -109,16 +110,21 @@ public class ReportGenerator { * @param generalModuleStates the enabled/disabled state of each GeneralReportModule */ private void setupProgressPanels(Map tableModuleStates, Map generalModuleStates) { - for (Entry entry : tableModuleStates.entrySet()) { - if (entry.getValue()) { - TableReportModule module = entry.getKey(); - tableProgress.put(module, panel.addReport(module.getName(), reportPath + module.getFilePath())); + if (null != tableModuleStates) { + for (Entry entry : tableModuleStates.entrySet()) { + if (entry.getValue()) { + TableReportModule module = entry.getKey(); + tableProgress.put(module, panel.addReport(module.getName(), reportPath + module.getFilePath())); + } } } - for (Entry entry : generalModuleStates.entrySet()) { - if (entry.getValue()) { - GeneralReportModule module = entry.getKey(); - generalProgress.put(module, panel.addReport(module.getName(), reportPath + module.getFilePath())); + + if (null != generalModuleStates) { + for (Entry entry : generalModuleStates.entrySet()) { + if (entry.getValue()) { + GeneralReportModule module = entry.getKey(); + generalProgress.put(module, panel.addReport(module.getName(), reportPath + module.getFilePath())); + } } } } @@ -171,8 +177,10 @@ public class ReportGenerator { * @param tagSelections the enabled/disabled state of the tags to be included in the report */ public void generateArtifactTableReports(Map artifactTypeSelections, Map tagSelections) { - ArtifactsReportsWorker worker = new ArtifactsReportsWorker(artifactTypeSelections, tagSelections); - worker.execute(); + if (!tableProgress.isEmpty() && null != artifactTypeSelections) { + ArtifactsReportsWorker worker = new ArtifactsReportsWorker(artifactTypeSelections, tagSelections); + worker.execute(); + } } /** @@ -216,7 +224,7 @@ public class ReportGenerator { } // Get the tags selected by the user. - if (tagSelections != null) { + if (null != tagSelections) { for (Entry entry : tagSelections.entrySet()) { if (entry.getValue() == true) { tagNamesFilter.add(entry.getKey()); diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java b/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java index dbe63a4b64..11201aaaed 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportWizardAction.java @@ -64,38 +64,13 @@ public final class ReportWizardAction extends CallableSystemAction implements P * and start all necessary reports. */ public static void doReportWizard() { - // Create the wizard WizardDescriptor wiz = new WizardDescriptor(new ReportWizardIterator()); wiz.setTitleFormat(new MessageFormat("{0} {1}")); - wiz.setTitle("Generate Report"); - - // When the user presses the finish button + wiz.setTitle("Generate Report"); if (DialogDisplayer.getDefault().notify(wiz) == WizardDescriptor.FINISH_OPTION) { - // Get the wizard information - Object wizProp1 = wiz.getProperty("tableModuleStates"); - Object wizProp2 = wiz.getProperty("generalModuleStates"); - Object wizProp3 = wiz.getProperty("isTagsSelected"); - Object wizProp4 = wiz.getProperty("tagStates"); - Object wizProp5 = wiz.getProperty("artifactStates"); - - // Initialize variables - Map tableModuleStates = (Map) wizProp1; - Map generalModuleStates = (Map) wizProp2; - Boolean isTagsSelected = (Boolean) wizProp3; - Map tagSelections = (Map) wizProp4; - Map artifactTypeSelections = (Map) wizProp5; - - // Create the generator and generate reports - ReportGenerator generator = new ReportGenerator(tableModuleStates, generalModuleStates); - if (isTagsSelected) { - generator.generateArtifactTableReports(artifactTypeSelections, tagSelections); - } - else { - generator.generateArtifactTableReports(artifactTypeSelections, null); - } + ReportGenerator generator = new ReportGenerator((Map)wiz.getProperty("tableModuleStates"), (Map)wiz.getProperty("generalModuleStates")); + generator.generateArtifactTableReports((Map)wiz.getProperty("artifactStates"), (Map)wiz.getProperty("tagStates")); generator.generateGeneralReports(); - - // Open the progress window for the user generator.displayProgressPanels(); } } diff --git a/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java b/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java index d2fdbb6907..e009b18bfe 100644 --- a/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java +++ b/ExifParser/src/org/sleuthkit/autopsy/exifparser/ExifParserFileIngestModule.java @@ -214,7 +214,10 @@ public final class ExifParserFileIngestModule extends IngestModuleAbstractFile { if (bytesRead != 2) { return false; } - if ((fileHeaderBuffer[0] == 0xff) && (fileHeaderBuffer[1] == 0xd8)) { + /* Check for the JPEG header. + * Since Java bytes are signed, we cast them to an int first. + */ + if (((int)(fileHeaderBuffer[0] & 0xff) == 0xff) && ((int)(fileHeaderBuffer[1] & 0xff) == 0xd8)) { return true; } return false; diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java index 228cbf34d3..f421d89c52 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/KeywordSearchSettings.java @@ -40,7 +40,7 @@ public class KeywordSearchSettings { static final String PROPERTIES_SCRIPTS = MODULE_NAME+"_Scripts"; private static boolean skipKnown = true; private static final Logger logger = Logger.getLogger(KeywordSearchSettings.class.getName()); - private static UpdateFrequency UpdateFreq = UpdateFrequency.AVG; + private static UpdateFrequency UpdateFreq = UpdateFrequency.DEFAULT; private static List stringExtractScripts = new ArrayList(); private static Map stringExtractOptions = new HashMap(); @@ -190,7 +190,7 @@ public class KeywordSearchSettings { //setting default Update Frequency if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, "UpdateFrequency")){ logger.log(Level.INFO, "No configuration for Update Frequency found, generating default..."); - KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.AVG); + KeywordSearchSettings.setUpdateFrequency(UpdateFrequency.DEFAULT); } //setting default Extract UTF8 if(!ModuleSettings.settingExists(KeywordSearchSettings.PROPERTIES_OPTIONS, AbstractFileExtract.ExtractOptions.EXTRACT_UTF8.toString())){ 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 8d7719d668..0c8b9abcbd 100644 --- a/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties +++ b/branding/core/core.jar/org/netbeans/core/startup/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Wed, 07 Aug 2013 08:19:27 -0400 +#Fri, 23 Aug 2013 15:47:56 -0400 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=288 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=5,266,530,17 SplashRunningTextColor=0x0 SplashRunningTextFontSize=18 -currentVersion=Autopsy 20130807 +currentVersion=Autopsy 20130823 diff --git a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties index e718444a20..60b4d85f0e 100644 --- a/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties +++ b/branding/modules/org-netbeans-core-windows.jar/org/netbeans/core/windows/view/ui/Bundle.properties @@ -1,5 +1,5 @@ #Updated by build script -#Wed, 07 Aug 2013 08:19:27 -0400 +#Fri, 23 Aug 2013 15:47:56 -0400 -CTL_MainWindow_Title=Autopsy 20130807 -CTL_MainWindow_Title_No_Project=Autopsy 20130807 +CTL_MainWindow_Title=Autopsy 20130823 +CTL_MainWindow_Title_No_Project=Autopsy 20130823