From 2e5017d1b7b31f59013a6a656736b1dfabff20c5 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Mon, 24 Sep 2018 17:25:20 +0200 Subject: [PATCH 1/4] fix pragma usage --- .../imagegallery/actions/OpenAction.java | 10 +++-- .../imagegallery/datamodel/DrawableDB.java | 38 ++++++++++++++++--- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index efbdc3de00..e444769889 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -143,7 +143,7 @@ public final class OpenAction extends CallableSystemAction { return; } try { - ImageGalleryController controller = ImageGalleryModule.getController(); + ImageGalleryController controller = ImageGalleryModule.getController(); if (controller.isDataSourcesTableStale()) { //drawable db is stale, ask what to do int answer = JOptionPane.showConfirmDialog( @@ -162,9 +162,13 @@ public final class OpenAction extends CallableSystemAction { * user may want to review images, so we rebuild the * database only when a user launches Image Gallery. */ - - if (currentCase.getCaseType() == Case.CaseType.SINGLE_USER_CASE) { + /* + * Turning listening off is necessary in order to + * invoke the listener that will call + * controller.rebuildDB(); + */ + controller.setListeningEnabled(false); controller.setListeningEnabled(true); } else { controller.rebuildDB(); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index f779978dfb..ced28699dd 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -347,8 +347,10 @@ public final class DrawableDB { } /** - * public factory method. Creates and opens a connection to a new database * - * at the given path. * + * Public factory method. Creates and opens a connection to a new database * + * at the given path. If there is already a db at the path, it is checked + * for compatibility, and deleted if it is incompatible, before a connection + * is opened. * * @param controller * @@ -357,16 +359,42 @@ public final class DrawableDB { * @throws org.sleuthkit.datamodel.TskCoreException */ public static DrawableDB getDrawableDB(ImageGalleryController controller) throws TskCoreException { - Path dbPath = ImageGalleryModule.getModuleOutputDir(controller.getAutopsyCase()); + Path dbPath = ImageGalleryModule.getModuleOutputDir(controller.getAutopsyCase()).resolve("drawable.db"); + boolean hasDataSourceObjIdColumn = hasDataSourceObjIdColumn(dbPath); try { - return new DrawableDB(dbPath.resolve("drawable.db"), controller); //NON-NLS + if (hasDataSourceObjIdColumn == false) { + Files.deleteIfExists(dbPath); + } + } catch (IOException ex) { + throw new TskCoreException("Error deleting old database", ex); //NON-NLS + } + + try { + return new DrawableDB(dbPath, controller); //NON-NLS } catch (SQLException ex) { - throw new TskCoreException("sql error creating database connection", ex); //NON-NLS + throw new TskCoreException("SQL error creating database connection", ex); //NON-NLS } catch (IOException ex) { throw new TskCoreException("Error creating database connection", ex); //NON-NLS } } + private static boolean hasDataSourceObjIdColumn(Path dbPath1) throws TskCoreException { + String sql = "pragma table_info('drawable_files')"; //NON-NLS + try (Connection con = DriverManager.getConnection("jdbc:sqlite:" + dbPath1.toString()); //NON-NLS + Statement stmt = con.createStatement(); + ResultSet results = stmt.executeQuery(sql);) { + while (results.next()) { + if ("data_source_obj_id".equals(results.getString("name"))) { + return true; + } + } + + } catch (SQLException ex) { + throw new TskCoreException("SQL error checking database compatibility", ex); //NON-NLS + } + return false; + } + private void setPragmas() throws SQLException { //this should match Sleuthkit db setupt From ba728652980c18931d3f75b57a1fcf843328be01 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Wed, 26 Sep 2018 12:21:00 +0200 Subject: [PATCH 2/4] cleanup --- .../imagegallery/ImageGalleryModule.java | 59 ++++++++++--------- .../ImageGalleryOptionsPanel.java | 9 ++- .../ImageGalleryTopComponent.java | 22 ++++--- .../imagegallery/actions/OpenAction.java | 6 +- .../imagegallery/datamodel/DrawableDB.java | 6 +- .../datamodel/grouping/DrawableGroup.java | 8 ++- 6 files changed, 64 insertions(+), 46 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java index 90634093ee..08f06a2788 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java @@ -27,6 +27,7 @@ import javafx.application.Platform; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import static org.apache.commons.lang3.StringUtils.isNotBlank; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; @@ -57,14 +58,10 @@ public class ImageGalleryModule { private static final Object controllerLock = new Object(); private static ImageGalleryController controller; - public static ImageGalleryController getController() throws NoCurrentCaseException { + public static ImageGalleryController getController() throws TskCoreException, NoCurrentCaseException { synchronized (controllerLock) { if (controller == null) { - try { - controller = new ImageGalleryController(Case.getCurrentCaseThrows()); - } catch (NoCurrentCaseException | TskCoreException ex) { - throw new NoCurrentCaseException("Error getting ImageGalleryController for the current case.", ex); - } + controller = new ImageGalleryController(Case.getCurrentCaseThrows()); } return controller; } @@ -192,6 +189,8 @@ public class ImageGalleryModule { } } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS } } } @@ -218,6 +217,9 @@ public class ImageGalleryModule { } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS return; + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS + return; } switch (Case.Events.valueOf(evt.getPropertyName())) { case CURRENT_CASE: @@ -288,31 +290,32 @@ public class ImageGalleryModule { } // A remote node added a new data source and just finished ingest on it. //drawable db is stale, and if ImageGallery is open, ask user what to do - ImageGalleryController con; + try { - con = getController(); + ImageGalleryController con = getController(); + con.setStale(true); + if (con.isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) { + SwingUtilities.invokeLater(() -> { + int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(), + Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(), + Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(), + JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); + + switch (showAnswer) { + case JOptionPane.YES_OPTION: + con.rebuildDB(); + break; + case JOptionPane.NO_OPTION: + case JOptionPane.CANCEL_OPTION: + default: + break; //do nothing + } + }); + } } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS - return; - } - con.setStale(true); - if (con.isListeningEnabled() && ImageGalleryTopComponent.isImageGalleryOpen()) { - SwingUtilities.invokeLater(() -> { - int showAnswer = JOptionPane.showConfirmDialog(ImageGalleryTopComponent.getTopComponent(), - Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_msg(), - Bundle.ImageGalleryController_dataSourceAnalyzed_confDlg_title(), - JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.WARNING_MESSAGE); - - switch (showAnswer) { - case JOptionPane.YES_OPTION: - con.rebuildDB(); - break; - case JOptionPane.NO_OPTION: - case JOptionPane.CANCEL_OPTION: - default: - break; //do nothing - } - }); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS } } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryOptionsPanel.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryOptionsPanel.java index 80c35be23b..df0dacd3fe 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryOptionsPanel.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryOptionsPanel.java @@ -18,21 +18,26 @@ */ package org.sleuthkit.autopsy.imagegallery; +import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.ingest.IngestManager; +import org.sleuthkit.datamodel.TskCoreException; /** * The Image/Video Gallery panel in the NetBeans provided Options Dialogs * accessed via Tools -> Options * - * Uses {@link ImageGalleryPreferences} and {@link PerCaseProperties} to persist + * Uses ImageGalleryPreferences and PerCaseProperties to persist * settings */ @SuppressWarnings("PMD.SingularField") // UI widgets cause lots of false positives final class ImageGalleryOptionsPanel extends javax.swing.JPanel { + private static final Logger logger = Logger.getLogger(ImageGalleryOptionsPanel.class.getName()); + ImageGalleryOptionsPanel(ImageGalleryOptionsPanelController controller) { initComponents(); @@ -206,6 +211,8 @@ final class ImageGalleryOptionsPanel extends javax.swing.JPanel { new PerCaseProperties(openCase).setConfigSetting(ImageGalleryModule.getModuleName(), PerCaseProperties.ENABLED, Boolean.toString(enabledForCaseBox.isSelected())); } catch (NoCurrentCaseException ex) { // It's not an error if there's no case open + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java index a1238185ea..c6c82609ca 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryTopComponent.java @@ -50,6 +50,7 @@ import static org.apache.commons.collections4.CollectionUtils.isNotEmpty; import static org.apache.commons.lang3.ObjectUtils.notEqual; import org.openide.explorer.ExplorerManager; import org.openide.explorer.ExplorerUtils; +import org.openide.util.Exceptions; import org.openide.util.Lookup; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; @@ -147,7 +148,7 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl "ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.contentText=Data source:", "ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.all=All", "ImageGalleryTopComponent.openTopCommponent.chooseDataSourceDialog.titleText=Image Gallery",}) - public static void openTopComponent() throws NoCurrentCaseException { + public static void openTopComponent() throws NoCurrentCaseException, TskCoreException { final TopComponent topComponent = WindowManager.getDefault().findTopComponent(PREFERRED_ID); if (topComponent == null) { @@ -159,14 +160,11 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl return; } - List dataSources = Collections.emptyList(); ImageGalleryController controller = ImageGalleryModule.getController(); ((ImageGalleryTopComponent) topComponent).setController(controller); - try { - dataSources = controller.getSleuthKitCase().getDataSources(); - } catch (TskCoreException tskCoreException) { - logger.log(Level.SEVERE, "Unable to get data sourcecs.", tskCoreException); - } + + List dataSources = controller.getSleuthKitCase().getDataSources(); + GroupManager groupManager = controller.getGroupManager(); synchronized (groupManager) { if (dataSources.size() <= 1 @@ -222,10 +220,16 @@ public final class ImageGalleryTopComponent extends TopComponent implements Expl } } - public ImageGalleryTopComponent() throws NoCurrentCaseException { + public ImageGalleryTopComponent() { setName(Bundle.CTL_ImageGalleryTopComponent()); initComponents(); - setController(ImageGalleryModule.getController()); + try { + setController(ImageGalleryModule.getController()); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS + } } synchronized private void setController(ImageGalleryController controller) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java index e444769889..d33f41a715 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/actions/OpenAction.java @@ -187,8 +187,10 @@ public final class OpenAction extends CallableSystemAction { //drawable db is not stale, just open it ImageGalleryTopComponent.openTopComponent(); } - } catch (NoCurrentCaseException noCurrentCaseException) { - logger.log(Level.WARNING, "There was no case open when Image Gallery was opened.", noCurrentCaseException); + } catch (NoCurrentCaseException ex) { + logger.log(Level.SEVERE, "Attempted to access ImageGallery with no case open.", ex); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index ced28699dd..4c3b4cb29e 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -378,9 +378,9 @@ public final class DrawableDB { } } - private static boolean hasDataSourceObjIdColumn(Path dbPath1) throws TskCoreException { - String sql = "pragma table_info('drawable_files')"; //NON-NLS - try (Connection con = DriverManager.getConnection("jdbc:sqlite:" + dbPath1.toString()); //NON-NLS + private static boolean hasDataSourceObjIdColumn(Path dbPath) throws TskCoreException { + String sql = "PRAGMA table_info('drawable_files')"; //NON-NLS + try (Connection con = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toString()); //NON-NLS Statement stmt = con.createStatement(); ResultSet results = stmt.executeQuery(sql);) { while (results.next()) { diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/DrawableGroup.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/DrawableGroup.java index 224ac378c6..bdb54c448f 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/DrawableGroup.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/DrawableGroup.java @@ -46,7 +46,7 @@ import org.sleuthkit.datamodel.TskCoreException; */ public class DrawableGroup implements Comparable { - private static final Logger LOGGER = Logger.getLogger(DrawableGroup.class.getName()); + private static final Logger logger = Logger.getLogger(DrawableGroup.class.getName()); public static String getBlankGroupName() { return "unknown"; @@ -128,7 +128,9 @@ public class DrawableGroup implements Comparable { .filter(Boolean::booleanValue) .count()); } catch (NoCurrentCaseException ex) { - LOGGER.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS + logger.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, "Error getting ImageGalleryController.", ex); //NON-NLS } } return hashSetHitsCount.get(); @@ -145,7 +147,7 @@ public class DrawableGroup implements Comparable { uncatCount.set(ImageGalleryModule.getController().getDatabase().getUncategorizedCount(fileIDs)); } catch (TskCoreException | NoCurrentCaseException ex) { - LOGGER.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS + logger.log(Level.WARNING, "Could not access case during getFilesWithHashSetHitsCount()"); //NON-NLS } } From a341eee92adb7da69f5db766240fe50981dfc410 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Thu, 27 Sep 2018 14:32:34 +0200 Subject: [PATCH 3/4] check for table before checking for column to avoid "query doesn't return ResultSet"error --- .../imagegallery/datamodel/DrawableDB.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index 4c3b4cb29e..ee447f66ba 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -379,13 +379,26 @@ public final class DrawableDB { } private static boolean hasDataSourceObjIdColumn(Path dbPath) throws TskCoreException { - String sql = "PRAGMA table_info('drawable_files')"; //NON-NLS try (Connection con = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toString()); //NON-NLS - Statement stmt = con.createStatement(); - ResultSet results = stmt.executeQuery(sql);) { - while (results.next()) { - if ("data_source_obj_id".equals(results.getString("name"))) { - return true; + Statement stmt = con.createStatement();) { + boolean tableExists = false; + try (ResultSet results = stmt.executeQuery("SELECT name FROM sqlite_master WHERE type='table'");) {//NON-NLS + while (results.next()) { + if ("drawable_files".equals(results.getString("name"))) { + tableExists = true; + break; + } + } + } + if (false == tableExists) { + return false; + } else { + try (ResultSet results = stmt.executeQuery("PRAGMA table_info('drawable_files')");) { //NON-NLS + while (results.next()) { + if ("data_source_obj_id".equals(results.getString("name"))) { + return true; + } + } } } From b80344587dbf194523cfda5cd5f93151c925ffa5 Mon Sep 17 00:00:00 2001 From: millmanorama Date: Thu, 27 Sep 2018 15:23:23 +0200 Subject: [PATCH 4/4] cleanup --- .../imagegallery/datamodel/DrawableDB.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index ee447f66ba..c3f9ebbee3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -378,7 +378,16 @@ public final class DrawableDB { } } + /** + * Check if the db at the given path has the data_source_obj_id column. If + * the db doesn't exist or doesn't even have the drawable_files table, this + * method returns false. + * + * NOTE: This method makes an ad-hoc connection to db, which has the side + * effect of creating the drawable.db file if it didn't already exist. + */ private static boolean hasDataSourceObjIdColumn(Path dbPath) throws TskCoreException { + try (Connection con = DriverManager.getConnection("jdbc:sqlite:" + dbPath.toString()); //NON-NLS Statement stmt = con.createStatement();) { boolean tableExists = false; @@ -392,16 +401,14 @@ public final class DrawableDB { } if (false == tableExists) { return false; - } else { - try (ResultSet results = stmt.executeQuery("PRAGMA table_info('drawable_files')");) { //NON-NLS - while (results.next()) { - if ("data_source_obj_id".equals(results.getString("name"))) { - return true; - } + } + try (ResultSet results = stmt.executeQuery("PRAGMA table_info('drawable_files')");) { //NON-NLS + while (results.next()) { + if ("data_source_obj_id".equals(results.getString("name"))) { + return true; } } } - } catch (SQLException ex) { throw new TskCoreException("SQL error checking database compatibility", ex); //NON-NLS }