From c10e2b4b311d4efcf82463d4ef49e07a9fffee50 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 21 Aug 2013 15:06:08 -0400 Subject: [PATCH 01/27] Deleted smaller new case icon --- .../casemodule/btn_icon_create_new_case-24.png | Bin 1144 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100755 Core/src/org/sleuthkit/autopsy/casemodule/btn_icon_create_new_case-24.png diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/btn_icon_create_new_case-24.png b/Core/src/org/sleuthkit/autopsy/casemodule/btn_icon_create_new_case-24.png deleted file mode 100755 index cdc98334cc921098d6b59b5339490ae78bc38bbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1144 zcmV-;1c&>HP)@7~>e*{+hrN@FWhH561*^+l>s5$sFx*$*t_MJo8E@}Y1$;)ZcKM`_kPTb59x;6?Pl8p17~LL zJ^%Ut&p9)KJ2o~pCS2Ebi^U?=T6&off>x_VqtQsVZr!STeJfWTDW8{8hEmGVahwMl zuIqkq`0!!b3qZ9U-}gPw^C*={tEUt~Af-eIvAWi_D2j-pXs_pats_T{?BBU_XVjB{ z&FIn@ygjmeT5HPXa-pxUZ{N_+(8!)Wdt^_5j8u1xHc+>rwI&DxcVJ*(-^j?w`+(>P z&>5_gMJFRESAGwIAU`-b_{HVRmp=kHd-klnCkJhXx&_E;pZ%uMXb^^Bd#&jE{wL?o zom)3NJpA!J46=cH1#cgwP$=Me9!e>cQb;NBSL~gxRg{$|JMZSVbLG13UF@~ixUTE; zOmb({ti__+ezv5$GFYo?yP4JrOUv_w(GsbS$*UrsTVA`-9>lD*2q9RgUtxUuIHh7h z!7ZX3MZFoa+-ed<`k|f@-H**|ZGsaQzTvUKjRX}v_ zM4B8*IgFmZ#O$@3D5WU4F2|0ZCP`A>+_jxbE&zR-RL9Pm5*cHVQm)P&nI}yIsZNN~ z7Q5bl7cW=l;`m=2{OKT{f4Uc)TB`LkBzl=tr$k9oTa$s5a@7YYx$Ce|3C$wbTCUd5 z0G4Zu3+NOk=8lu51}PLmK&xp9o5_JJfXL>dU8-%l%0VBVe1zKERVsZ&j9Fo}`H3eP z-u*hY_zwgUO$xyEYCUPS;;*u0YC2!D&PsaunYXA_p;lWWF$sxDXrwooO;3^ Date: Fri, 23 Aug 2013 12:40:11 -0400 Subject: [PATCH 02/27] Added necessary null pointer check to static initializer of Tags class --- .../org/sleuthkit/autopsy/datamodel/Tags.java | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) 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) { From dc67e309b520802490e11f6c50ac9cfd7df19516 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Fri, 23 Aug 2013 13:11:08 -0400 Subject: [PATCH 04/27] Move the About box Close button to a more reasonable location. --- .../org/netbeans/core/windows/view/ui/Bundle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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..be1ae09a6d 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 13:08:16 -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 From 8260085809b34d2642671aa7e4ce12174795259b Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 23 Aug 2013 13:37:35 -0400 Subject: [PATCH 05/27] Made the ReportGenerator able to handle the situation when there are no artifact table reports to be generated --- .../autopsy/report/ReportGenerator.java | 40 +++++++++++-------- .../autopsy/report/ReportWizardAction.java | 31 ++------------ 2 files changed, 27 insertions(+), 44 deletions(-) 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(); } } From 7b418369bddc2241a4e9067fb50ed63c20a0cadb Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Fri, 23 Aug 2013 16:39:59 -0400 Subject: [PATCH 06/27] CueBannerPanel (the startup panel) now takes an image path in its constructor, which is useful for NB modules that want to change the logo. --- .../autopsy/casemodule/CueBannerPanel.java | 16 +++++++++++++--- .../autopsy/casemodule/StartupWindow.java | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index 501b1f488e..d28c040669 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -24,6 +24,7 @@ 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; @@ -45,9 +46,18 @@ 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() { + /** Creates new form CueBannerPanel + * + * @param welcomeLogo Java-centric path to an image file, e.g. "/org/sleuthkit/autopsy/casemodule/welcome_logo.png". + */ + public CueBannerPanel(String welcomeLogo) { initComponents(); + ImageIcon icon = null; + ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class); + if (cl != null) { + icon = new ImageIcon(cl.getResource(welcomeLogo)); + } + autopsyLogo.setIcon(icon); //if null then no icon will be shown } /** This method is called from within the constructor to @@ -254,7 +264,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..f6f9f540bd 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java @@ -58,8 +58,8 @@ 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(); + + CueBannerPanel welcomeWindow = new CueBannerPanel("/org/sleuthkit/autopsy/casemodule/welcome_logo.png"); // add the command to close the window to the button on the Volume Detail Panel welcomeWindow.setCloseButtonActionListener(new ActionListener() { From 07bd6905e0e1844c3de27130f3e3c7f3831dadf4 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Fri, 23 Aug 2013 16:43:16 -0400 Subject: [PATCH 07/27] Changes so that NB modules can set custom copyright text in the About box. Also the proper commit for previous "Move the About box Close button to a more reasonable location." --- .../ProductInformationPanel.form | 62 +++++++++---------- .../ProductInformationPanel.java | 61 +++++++++--------- 2 files changed, 59 insertions(+), 64 deletions(-) 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()) { From c86345d7ee3ac5e310d4cb9297b51e827e82d82f Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Fri, 23 Aug 2013 16:44:49 -0400 Subject: [PATCH 08/27] Latest timestamps. --- .../core/core.jar/org/netbeans/core/startup/Bundle.properties | 4 ++-- .../org/netbeans/core/windows/view/ui/Bundle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 be1ae09a6d..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 -#Fri, 23 Aug 2013 13:08:16 -0400 +#Fri, 23 Aug 2013 15:47:56 -0400 CTL_MainWindow_Title=Autopsy 20130823 CTL_MainWindow_Title_No_Project=Autopsy 20130823 From 1366f6e26878aa7b84c77f72c32725ac57f2bc0f Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Sat, 24 Aug 2013 23:22:41 -0400 Subject: [PATCH 09/27] added no arg constructor back to CueBannerPanel --- .../autopsy/casemodule/CueBannerPanel.java | 16 ++++++---------- .../autopsy/casemodule/StartupWindow.java | 2 +- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java index d28c040669..49c5b313a0 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CueBannerPanel.java @@ -29,12 +29,9 @@ 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 { @@ -46,18 +43,17 @@ public class CueBannerPanel extends javax.swing.JPanel { private static JPanel caller = new JPanel(); private String className = this.getClass().toString(); - /** Creates new form CueBannerPanel - * - * @param welcomeLogo Java-centric path to an image file, e.g. "/org/sleuthkit/autopsy/casemodule/welcome_logo.png". - */ + public CueBannerPanel() { + initComponents(); + } + public CueBannerPanel(String welcomeLogo) { initComponents(); - ImageIcon icon = null; ClassLoader cl = Lookup.getDefault().lookup(ClassLoader.class); if (cl != null) { - icon = new ImageIcon(cl.getResource(welcomeLogo)); + ImageIcon icon = new ImageIcon(cl.getResource(welcomeLogo)); + autopsyLogo.setIcon(icon); } - autopsyLogo.setIcon(icon); //if null then no icon will be shown } /** This method is called from within the constructor to diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java index f6f9f540bd..f100123479 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/StartupWindow.java @@ -59,7 +59,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("/org/sleuthkit/autopsy/casemodule/welcome_logo.png"); + CueBannerPanel welcomeWindow = new CueBannerPanel(); // add the command to close the window to the button on the Volume Detail Panel welcomeWindow.setCloseButtonActionListener(new ActionListener() { From 2a1670011e61e218499fb01f607c344d62da9c3a Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 27 Aug 2013 10:25:00 -0400 Subject: [PATCH 10/27] File size views do not show unalloc files --- .../sleuthkit/autopsy/datamodel/FileSize.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) 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) { From ce4d55c3964eb0628f5cd921a7b19594d61403c0 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 27 Aug 2013 15:05:06 -0400 Subject: [PATCH 11/27] Extended multi-select features to thumbnail data result viewer --- .../DataResultViewer.java | 2 +- .../AbstractDataResultViewer.java | 17 +++-- .../corecomponents/DataResultPanel.java | 50 +++++++------ .../DataResultTopComponent.java | 72 +++++++------------ .../corecomponents/DataResultViewerTable.java | 43 ++++++++--- .../DataResultViewerThumbnail.java | 45 +++++++++--- 6 files changed, 128 insertions(+), 101 deletions(-) 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..788393803a 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,8 +39,7 @@ 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(); @@ -120,12 +119,12 @@ public abstract class AbstractDataResultViewer extends JPanel implements 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); - } +// 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/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..9be30e0e2e 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,49 @@ 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) { + // @@@ This is a temporary hack until DataResultViewers can be made + // compatible with node multiple selection actions. The ExplorerManager + // constructed in the base class is being replaced with the one passed + // in. Note that this assignment must be done before calling + // initComponents() so that the child OutlineView component can obtain + // the ExplorerManager via its call to ExplorerManager.find(). + // ExplorerManager.find() searches the ancestors of a Swing component + // for an implementer of the ExplorerManager.Provider interface; the + // base class of this class, AbstractDataResultViewer, is an implementer + // of that interface. + em = 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 +93,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 +462,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.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index f63e4944c8..0bf4385ff1 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"); @@ -29,6 +29,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 +38,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 +50,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()); @@ -61,22 +64,43 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { 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) { + // @@@ This is a temporary hack until DataResultViewers can be made + // compatible with node multiple selection actions. The ExplorerManager + // constructed in the base class is being replaced with the one passed + // in. Note that this assignment must be done before calling + // initComponents() so that the child IconView component can obtain + // the ExplorerManager via its call to ExplorerManager.find(). + // ExplorerManager.find() searches the ancestors of a Swing component + // for an implementer of the ExplorerManager.Provider interface; the + // base class of this class, AbstractDataResultViewer, is an implementer + // of that interface. + em = 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 @@ -315,7 +339,6 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { this.thumbnailScrollPanel.removeAll(); this.thumbnailScrollPanel = null; - //this destroyes em super.clearComponent(); } From 8a678b13d1d5d70b2213365c1fb2afb650ca39b6 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 27 Aug 2013 15:15:03 -0400 Subject: [PATCH 13/27] Removed destruction of ExplorerManager by AbstractDataResultViewer --- .../autopsy/corecomponents/AbstractDataResultViewer.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java index 788393803a..b0e0f06904 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java @@ -118,13 +118,6 @@ public abstract class AbstractDataResultViewer extends JPanel implements DataRes @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 From 6e7d053bf6047b83c601dc7a2777fa56fe7f2b12 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Tue, 27 Aug 2013 20:10:50 -0400 Subject: [PATCH 14/27] Added icon size control to DataResultViewerThumbnail GUI and size changing mechanism in ThumbnailViewNode. --- .../DataResultViewerThumbnail.form | 18 +++++++ .../DataResultViewerThumbnail.java | 50 ++++++++++++++++--- .../corecomponents/ThumbnailViewNode.java | 26 +++++++++- 3 files changed, 85 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form index 48d26daaa7..28f3146098 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..8a2ac90496 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -97,6 +97,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 +147,14 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { } }); + thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Small", "Medium", "Large" })); + 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 +181,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 +200,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 +221,30 @@ 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 + + int newSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; //default size + switch(thumbnailSizeComboBox.getSelectedIndex()) { + case 0: + newSize = ThumbnailViewNode.ICON_SIZE_SMALL; + break; + case 2: + newSize = ThumbnailViewNode.ICON_SIZE_LARGE; + break; + } + + ThumbnailViewNode.setIconSize(newSize); + + Node root = em.getRootContext(); + for (Node page : root.getChildren().getNodes()) { + for (Node node : page.getChildren().getNodes()) { + ThumbnailViewNode tn = (ThumbnailViewNode) node; + tn.setRefresh(true); + } + } + + }//GEN-LAST:event_thumbnailSizeComboBoxActionPerformed + // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel filePathLabel; private javax.swing.JTextField goToPageField; @@ -221,6 +257,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 @@ -247,7 +284,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { try { if (givenNode != null) { ThumbnailViewChildren childNode = new ThumbnailViewChildren(givenNode); - + final Node root = new AbstractNode(childNode); pageUpdater.setRoot(root); root.addNodeListener(pageUpdater); @@ -377,7 +414,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 +424,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/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java index ef562ae0c4..0415130541 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -52,6 +52,12 @@ class ThumbnailViewNode extends FilterNode { private SoftReference iconCache; 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 static int iconWidth = ICON_SIZE_MEDIUM; + private static int iconHeight = ICON_SIZE_MEDIUM; + private boolean refresh = false; //private final BufferedImage defaultIconBI; /** @@ -74,6 +80,10 @@ class ThumbnailViewNode extends FilterNode { public Image getIcon(int type) { Image icon = null; + if (refresh) { + iconCache = null; + } + if (iconCache != null) { icon = iconCache.get(); } @@ -83,7 +93,7 @@ class ThumbnailViewNode extends FilterNode { Content content = this.getLookup().lookup(Content.class); if (content != null) { - if (getFile(content.getId()).exists()) { + if (getFile(content.getId()).exists() && !refresh) { try { icon = ImageIO.read(getFile(content.getId())); if (icon == null) { @@ -109,6 +119,7 @@ class ThumbnailViewNode extends FilterNode { } iconCache = new SoftReference(icon); + refresh = false; } return icon; @@ -127,7 +138,7 @@ 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, iconWidth, iconHeight); return biScaled; }catch (OutOfMemoryError e) { logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e); @@ -151,4 +162,15 @@ class ThumbnailViewNode extends FilterNode { private static File getFile(long id) { return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".jpg"); } + + public static void setIconSize(int pixelSize) { + iconWidth = pixelSize; + iconHeight = pixelSize; + //setRefresh(true); + } + + public void setRefresh(boolean flag) { + refresh = flag; + } + } From 3dffccf5f1286bdca28ac67b467c580c2128ebc6 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 27 Aug 2013 20:29:41 -0400 Subject: [PATCH 15/27] Updated ExtractAction for multi-select --- .../autopsy/directorytree/ExtractAction.java | 249 +++++++++++------- 1 file changed, 153 insertions(+), 96 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java index 1442cb57cd..c704132648 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,195 @@ 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().getCaseDirectory())); + 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().getCaseDirectory())); + 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.getName()))); + } + doFileExtraction(e, fileExtractionTasks); + } + } + + private void doFileExtraction(ActionEvent e, ArrayList fileExtractionTasks) { + 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; + } + + 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); + 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) { + ExtractFscContentVisitor.extract(task.source, task.destination, progress, 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; } } } From 9dd8ba67db66a62483d3e568a429dd0ea1a8b4a6 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Aug 2013 10:32:40 -0400 Subject: [PATCH 16/27] Updated multi-file export to use unique names and to save to exports folder --- .../org/sleuthkit/autopsy/casemodule/Case.java | 13 +++++++++++++ .../autopsy/directorytree/ExtractAction.java | 17 ++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6c1d0d6db1..7096f241c2 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java @@ -575,6 +575,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/directorytree/ExtractAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java index c704132648..7b6259f034 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java @@ -90,7 +90,7 @@ public final class ExtractAction extends AbstractAction { private void extractFile(ActionEvent e, AbstractFile source) { JFileChooser fileChooser = new JFileChooser(); - fileChooser.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory())); + 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<>(); @@ -102,7 +102,7 @@ public final class ExtractAction extends AbstractAction { private void extractFiles(ActionEvent e, Collection selectedFiles) { JFileChooser folderChooser = new JFileChooser(); folderChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - folderChooser.setCurrentDirectory(new File(Case.getCurrentCase().getCaseDirectory())); + folderChooser.setCurrentDirectory(new File(Case.getCurrentCase().getExportDirectory())); if (folderChooser.showSaveDialog((Component)e.getSource()) == JFileChooser.APPROVE_OPTION) { File destinationFolder = folderChooser.getSelectedFile(); if (!destinationFolder.exists()) { @@ -118,22 +118,29 @@ public final class ExtractAction extends AbstractAction { ArrayList fileExtractionTasks = new ArrayList<>(); for (AbstractFile source : selectedFiles) { - fileExtractionTasks.add(new FileExtractionTask(source, new File(destinationFolder, source.getName()))); + 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); + //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)) { @@ -143,7 +150,7 @@ public final class ExtractAction extends AbstractAction { } else { it.remove(); - } + } } } From c802e6d679855de8f8b6c0a133a6690cb6665f5d Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Aug 2013 10:36:09 -0400 Subject: [PATCH 17/27] Updated log messages for ingest loader to help debug when modules are not found --- .../autopsy/ingest/IngestModuleLoader.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) 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) From 921bc96be54b3384175df82e2d3224eeedfcabc4 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 28 Aug 2013 14:12:33 -0400 Subject: [PATCH 18/27] Fix of bug injected by extension of multi-select to thumbnail viewer --- .../corecomponents/AbstractDataResultViewer.java | 15 ++++++++++++--- .../corecomponents/DataResultViewerTable.java | 12 +----------- .../corecomponents/DataResultViewerThumbnail.java | 12 +----------- 3 files changed, 14 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java index b0e0f06904..abd3643c68 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/AbstractDataResultViewer.java @@ -42,7 +42,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; 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 @@ -50,8 +50,17 @@ public abstract class AbstractDataResultViewer extends JPanel implements DataRes */ 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); @@ -112,9 +121,9 @@ public abstract class AbstractDataResultViewer extends JPanel implements DataRes } }; - em.addPropertyChangeListener(nodeSelListener); + em.addPropertyChangeListener(nodeSelListener); } - + @Override public void clearComponent() { em.removePropertyChangeListener(nodeSelListener); diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java index 9be30e0e2e..1b5440036d 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerTable.java @@ -59,17 +59,7 @@ public class DataResultViewerTable extends AbstractDataResultViewer { * multiple selection actions. */ public DataResultViewerTable(ExplorerManager explorerManager) { - // @@@ This is a temporary hack until DataResultViewers can be made - // compatible with node multiple selection actions. The ExplorerManager - // constructed in the base class is being replaced with the one passed - // in. Note that this assignment must be done before calling - // initComponents() so that the child OutlineView component can obtain - // the ExplorerManager via its call to ExplorerManager.find(). - // ExplorerManager.find() searches the ancestors of a Swing component - // for an implementer of the ExplorerManager.Provider interface; the - // base class of this class, AbstractDataResultViewer, is an implementer - // of that interface. - em = explorerManager; + super(explorerManager); initialize(); } diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index 0bf4385ff1..3f74c742b0 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -68,17 +68,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { * multiple selection actions. */ public DataResultViewerThumbnail(ExplorerManager explorerManager) { - // @@@ This is a temporary hack until DataResultViewers can be made - // compatible with node multiple selection actions. The ExplorerManager - // constructed in the base class is being replaced with the one passed - // in. Note that this assignment must be done before calling - // initComponents() so that the child IconView component can obtain - // the ExplorerManager via its call to ExplorerManager.find(). - // ExplorerManager.find() searches the ancestors of a Swing component - // for an implementer of the ExplorerManager.Provider interface; the - // base class of this class, AbstractDataResultViewer, is an implementer - // of that interface. - em = explorerManager; + super(explorerManager); initialize(); } From 5fd85d34938d8db6677242e03db2fa8a4e5d4bb6 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Wed, 28 Aug 2013 15:41:08 -0400 Subject: [PATCH 19/27] Added workaround to force update of IconView when changing icon size. Also added "thumbnail" text to the drop-down. --- .../corecomponents/DataResultViewerThumbnail.form | 7 +++---- .../corecomponents/DataResultViewerThumbnail.java | 14 ++++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form index 28f3146098..fa43e09733 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form @@ -203,12 +203,11 @@ - - - + + + - diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index 8a2ac90496..a30d206cec 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -147,8 +147,7 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { } }); - thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Small", "Medium", "Large" })); - thumbnailSizeComboBox.setSelectedIndex(1); + thumbnailSizeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Small Thumbnails", "Medium Thumbnails", "Large Thumbnails" })); thumbnailSizeComboBox.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { thumbnailSizeComboBoxActionPerformed(evt); @@ -241,8 +240,15 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { ThumbnailViewNode tn = (ThumbnailViewNode) node; tn.setRefresh(true); } - } - + } + + // 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 From 6907bc673582e8c251283c759b459019babdd69e Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Aug 2013 17:16:58 -0400 Subject: [PATCH 20/27] totally reset media player -- caused exception when setNode called multiple times with same file --- .../sleuthkit/autopsy/corecomponents/DataContentViewerMedia.java | 1 + 1 file changed, 1 insertion(+) 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(); } From 1049637421c7dcaa8af2e5eec2cfab65e2d47e3d Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Aug 2013 17:17:38 -0400 Subject: [PATCH 21/27] Disabled progress on file extraction. Caused exception with multiple files being exported --- .../org/sleuthkit/autopsy/directorytree/ExtractAction.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java index 7b6259f034..d645441fbc 100644 --- a/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java +++ b/Core/src/org/sleuthkit/autopsy/directorytree/ExtractAction.java @@ -205,15 +205,19 @@ public final class ExtractAction extends AbstractAction { }); progress.start(); progress.switchToIndeterminate(); + + /* @@@ Add back in -> Causes exceptions int workUnits = 0; for (FileExtractionTask task : extractionTasks) { workUnits += calculateProgressBarWorkUnits(task.source); } progress.switchToDeterminate(workUnits); + */ // Do the extraction tasks. for (FileExtractionTask task : this.extractionTasks) { - ExtractFscContentVisitor.extract(task.source, task.destination, progress, this); + // @@@ Note, we are no longer passing in progress + ExtractFscContentVisitor.extract(task.source, task.destination, null, this); } return null; From b1735e91309f34f7e10cbcc83b6442b0c3406271 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Aug 2013 17:18:02 -0400 Subject: [PATCH 22/27] Fixed bug with Exif code that was comparing with signed bytes to detect signature --- .../autopsy/exifparser/ExifParserFileIngestModule.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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; From d42bf2e77d53329d9e95f6b6f123da3e9296aae3 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 28 Aug 2013 17:47:25 -0400 Subject: [PATCH 23/27] Updated to make 5 minutes actually be default for keyword search --- .../autopsy/keywordsearch/KeywordSearchSettings.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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())){ From fc4b3c58cfadec61020b30157b69d6ebee494680 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Wed, 28 Aug 2013 17:55:54 -0400 Subject: [PATCH 24/27] Fix issues with thumbnail page displays not being in sync with the current global user-selected thumnail size. --- .../DataResultViewerThumbnail.form | 1 + .../DataResultViewerThumbnail.java | 11 +- .../corecomponents/ThumbnailViewNode.java | 104 ++++++++++-------- 3 files changed, 62 insertions(+), 54 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form index fa43e09733..14aac889e5 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.form @@ -208,6 +208,7 @@ + diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index a30d206cec..2243e9ce1a 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -148,6 +148,7 @@ 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); @@ -234,14 +235,8 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { ThumbnailViewNode.setIconSize(newSize); - Node root = em.getRootContext(); - for (Node page : root.getChildren().getNodes()) { - for (Node node : page.getChildren().getNodes()) { - ThumbnailViewNode tn = (ThumbnailViewNode) node; - tn.setRefresh(true); - } - } - + Node root = em.getRootContext(); + // 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 diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java index 0415130541..019543ae97 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -57,7 +57,8 @@ class ThumbnailViewNode extends FilterNode { static final int ICON_SIZE_LARGE = 200; private static int iconWidth = ICON_SIZE_MEDIUM; private static int iconHeight = ICON_SIZE_MEDIUM; - private boolean refresh = false; + private int curWidth = -1; + private int curHeight = -1; //private final BufferedImage defaultIconBI; /** @@ -79,52 +80,67 @@ class ThumbnailViewNode extends FilterNode { @Override public Image getIcon(int type) { Image icon = null; - - if (refresh) { - iconCache = null; - } - - if (iconCache != null) { - icon = iconCache.get(); - } - - - if (icon == null) { + + // If not the correct size, then make a new icon + if (curWidth != iconWidth) { Content content = this.getLookup().lookup(Content.class); - - if (content != null) { - if (getFile(content.getId()).exists() && !refresh) { - try { - icon = ImageIO.read(getFile(content.getId())); - if (icon == null) { - icon = ThumbnailViewNode.defaultIcon; - } - } 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 { - icon = ThumbnailViewNode.defaultIcon; + icon = generateAndSaveIcon(content); + iconCache = new SoftReference(icon); + } else { + + if (iconCache != null) { + icon = iconCache.get(); } - iconCache = new SoftReference(icon); - refresh = false; - } + 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) { + icon = ThumbnailViewNode.defaultIcon; + } + } catch (IOException ex) { + icon = ThumbnailViewNode.defaultIcon; + } + } else { // Make a new icon + icon = generateAndSaveIcon(content); + } + } else { + icon = ThumbnailViewNode.defaultIcon; + } + 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())); + curWidth = iconWidth; + curHeight = iconHeight; + } + } catch (IOException ex) { + logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex); + } + return icon; + } + /* * Generate a scaled image */ @@ -139,6 +155,7 @@ class ThumbnailViewNode extends FilterNode { return null; } BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconWidth, iconHeight); + return biScaled; }catch (OutOfMemoryError e) { logger.log(Level.WARNING, "Could not scale image (too large): " + content.getName(), e); @@ -166,11 +183,6 @@ class ThumbnailViewNode extends FilterNode { public static void setIconSize(int pixelSize) { iconWidth = pixelSize; iconHeight = pixelSize; - //setRefresh(true); } - - public void setRefresh(boolean flag) { - refresh = flag; - } - + } From 76b53db1b039051d6286daa6739a20f9706855a8 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Thu, 29 Aug 2013 16:49:26 -0400 Subject: [PATCH 25/27] Refactored so multiple instances of DataResultViewerThumbnail each maintain their own icon size. --- .../DataResultViewerThumbnail.java | 21 ++++-- .../corecomponents/ThumbnailViewChildren.java | 10 ++- .../corecomponents/ThumbnailViewNode.java | 74 +++++++++---------- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java index 2243e9ce1a..728990334b 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/DataResultViewerThumbnail.java @@ -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; @@ -58,6 +59,7 @@ 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(); /** @@ -223,19 +225,26 @@ public final class DataResultViewerThumbnail extends AbstractDataResultViewer { private void thumbnailSizeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_thumbnailSizeComboBoxActionPerformed - int newSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; //default size + iconSize = ThumbnailViewNode.ICON_SIZE_MEDIUM; //default size switch(thumbnailSizeComboBox.getSelectedIndex()) { case 0: - newSize = ThumbnailViewNode.ICON_SIZE_SMALL; + iconSize = ThumbnailViewNode.ICON_SIZE_SMALL; break; case 2: - newSize = ThumbnailViewNode.ICON_SIZE_LARGE; + iconSize = ThumbnailViewNode.ICON_SIZE_LARGE; break; } - ThumbnailViewNode.setIconSize(newSize); + Node root = em.getRootContext(); + for (Children c : Arrays.asList(root.getChildren()) ) { + ((ThumbnailViewChildren)c).setIconSize(iconSize); + } - Node root = em.getRootContext(); + 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 @@ -284,7 +293,7 @@ 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); 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 019543ae97..b69c7db3f5 100644 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/ThumbnailViewNode.java @@ -49,23 +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 static int iconWidth = ICON_SIZE_MEDIUM; - private static int iconHeight = ICON_SIZE_MEDIUM; - private int curWidth = -1; - private int curHeight = -1; + 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 @@ -80,41 +78,37 @@ class ThumbnailViewNode extends FilterNode { @Override public Image getIcon(int type) { Image icon = null; - - // If not the correct size, then make a new icon - if (curWidth != iconWidth) { + + if (iconCache != null) { + icon = iconCache.get(); + } + + if (icon == null) { Content content = this.getLookup().lookup(Content.class); - icon = generateAndSaveIcon(content); - iconCache = new SoftReference(icon); - } else { - - 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) { - icon = ThumbnailViewNode.defaultIcon; - } - } catch (IOException ex) { + if (content != null) { + // If a thumbnail file is already saved locally + if (getFile(content.getId()).exists()) { + try { + BufferedImage bicon = ImageIO.read(getFile(content.getId())); + if (bicon == null) { icon = ThumbnailViewNode.defaultIcon; + } else if (bicon.getWidth() != iconSize) { + icon = generateAndSaveIcon(content); + } else { + icon = bicon; } - } else { // Make a new icon - icon = generateAndSaveIcon(content); + } catch (IOException ex) { + icon = ThumbnailViewNode.defaultIcon; } - } else { - icon = ThumbnailViewNode.defaultIcon; + } else { // Make a new icon + icon = generateAndSaveIcon(content); } - - iconCache = new SoftReference(icon); + } else { + icon = ThumbnailViewNode.defaultIcon; } + + iconCache = new SoftReference(icon); } return icon; @@ -132,8 +126,6 @@ class ThumbnailViewNode extends FilterNode { f.delete(); } ImageIO.write((BufferedImage) icon, "jpg", getFile(content.getId())); - curWidth = iconWidth; - curHeight = iconHeight; } } catch (IOException ex) { logger.log(Level.WARNING, "Could not write cache thumbnail: " + content, ex); @@ -144,7 +136,7 @@ class ThumbnailViewNode extends FilterNode { /* * Generate a scaled image */ - static private BufferedImage generateIcon(Content content) { + private BufferedImage generateIcon(Content content) { InputStream inputStream = null; try { @@ -154,7 +146,7 @@ class ThumbnailViewNode extends FilterNode { logger.log(Level.WARNING, "No image reader for file: " + content.getName()); return null; } - BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconWidth, iconHeight); + BufferedImage biScaled = ScalrWrapper.resizeFast(bi, iconSize); return biScaled; }catch (OutOfMemoryError e) { @@ -180,9 +172,9 @@ class ThumbnailViewNode extends FilterNode { return new File(Case.getCurrentCase().getCacheDirectory() + File.separator + id + ".jpg"); } - public static void setIconSize(int pixelSize) { - iconWidth = pixelSize; - iconHeight = pixelSize; + public void setIconSize(int iconSize) { + this.iconSize = iconSize; + iconCache = null; } } From 96a5e5c7077c078b5d9edb650821f8536bb07549 Mon Sep 17 00:00:00 2001 From: "Samuel H. Kenyon" Date: Fri, 30 Aug 2013 15:38:55 -0400 Subject: [PATCH 26/27] Modified Case to not pull appName from Version statically; instead it now asks the MainWindow for its title and saves that as appName. --- Core/src/org/sleuthkit/autopsy/casemodule/Case.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/Case.java b/Core/src/org/sleuthkit/autopsy/casemodule/Case.java index 6c1d0d6db1..91c8a8ac5a 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; } From 13a2a6dcd0b6c710daa1e8702ae14b78c9a30770 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Tue, 3 Sep 2013 13:37:44 -0400 Subject: [PATCH 27/27] basic clean up, commenting, and renaming --- .../directorytree/DataResultFilterNode.java | 59 +++++++++++++------ .../DirectoryTreeTopComponent.java | 37 +++++------- 2 files changed, 56 insertions(+), 40 deletions(-) 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); } } });