From b8e5f0acede5e1fec99c010a024473bf008be84c Mon Sep 17 00:00:00 2001 From: Ann Priestman Date: Thu, 6 Feb 2020 10:22:09 -0500 Subject: [PATCH 01/77] Don't display block range for pool volume nodes --- .../sleuthkit/autopsy/datamodel/VolumeNode.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java index 541a842ea7..f8a6f2e5df 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/VolumeNode.java @@ -40,6 +40,7 @@ import org.sleuthkit.autopsy.directorytree.NewWindowViewAction; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.ModuleContentEvent; import org.sleuthkit.datamodel.Content; +import org.sleuthkit.datamodel.Pool; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.VirtualDirectory; import org.sleuthkit.datamodel.Volume; @@ -73,12 +74,22 @@ public class VolumeNode extends AbstractContentNode { */ public VolumeNode(Volume vol) { super(vol); - + // set name, display name, and icon String volName = nameForVolume(vol); - long end = vol.getStart() + (vol.getLength() - 1); String tempVolName = volName + " (" + vol.getDescription() + ": " + vol.getStart() + "-" + end + ")"; + + // If this is a pool volume use a custom display name + try { + if (vol.getParent() != null && + vol.getParent().getParent() instanceof Pool) { + // Pool volumes are not contiguous so printing a range of blocks is inaccurate + tempVolName = volName + " (" + vol.getDescription() + ": " + vol.getStart() + ")"; + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error looking up parent(s) of volume with obj ID = "+ vol.getId(), ex); + } this.setDisplayName(tempVolName); this.setIconBaseWithExtension("org/sleuthkit/autopsy/images/vol-icon.png"); //NON-NLS From 2542c75d743a77bdaffe56b8165690a8aff5c555 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 6 Feb 2020 16:54:59 -0500 Subject: [PATCH 02/77] Added support for TSK_GEO_WAYPOINTS attribute in TSK_GPS_ROUTE --- .../autopsy/geolocation/MapPanel.java | 3 - .../datamodel/Bundle.properties-MERGED | 1 + .../autopsy/geolocation/datamodel/Route.java | 127 ++++++++++++++---- .../geolocation/datamodel/Waypoint.java | 16 ++- .../datamodel/WaypointBuilder.java | 60 ++++----- .../android/googlemaplocation.py | 45 +++---- 6 files changed, 165 insertions(+), 87 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java index 4d286467b8..aa528f77de 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/MapPanel.java @@ -35,7 +35,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.logging.Level; @@ -58,7 +57,6 @@ import org.jxmapviewer.viewer.DefaultTileFactory; import org.jxmapviewer.viewer.GeoPosition; import org.jxmapviewer.viewer.TileFactory; import org.jxmapviewer.viewer.TileFactoryInfo; -import org.jxmapviewer.viewer.Waypoint; import org.jxmapviewer.viewer.WaypointPainter; import org.jxmapviewer.viewer.WaypointRenderer; import org.openide.util.NbBundle.Messages; @@ -69,7 +67,6 @@ import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException; import org.sleuthkit.datamodel.TskCoreException; import javax.imageio.ImageIO; import javax.swing.SwingUtilities; -import org.jxmapviewer.viewer.DefaultWaypointRenderer; /** * The map panel. This panel contains the jxmapviewer MapViewer diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED index a3ed4a8ad3..93f9329d9a 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED @@ -3,6 +3,7 @@ GEOTrack_point_label_header=Trackpoint for track: {0} LastKnownWaypoint_Label=Last Known Location Route_End_Label=End Route_Label=As-the-crow-flies Route +Route_point_label=Route point Route_Start_Label=Start SearchWaypoint_DisplayLabel=GPS Search TrackpointWaypoint_DisplayLabel=GPS Trackpoint diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index c08d2637ba..4181d96d14 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -25,14 +25,18 @@ import java.util.Map; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.GeoWaypoints; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint; /** * A Route represents a TSK_GPS_ROUTE artifact which has a start and end point - * however the class was written with the assumption that routes may have - * more that two points. + * however the class was written with the assumption that routes may have more + * that two points. * */ -public class Route extends GeoPath{ +public class Route extends GeoPath { + private final Long timestamp; // This list is not expected to change after construction so the @@ -51,12 +55,11 @@ public class Route extends GeoPath{ }) Route(BlackboardArtifact artifact) throws GeoLocationDataException { super(artifact, Bundle.Route_Label()); - + Map attributeMap = Waypoint.getAttributesFromArtifactAsMap(artifact); - - addToPath(getRouteStartPoint(artifact, attributeMap)); - addToPath(getRouteEndPoint(artifact, attributeMap)); - + + createRoute(artifact, attributeMap); + BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME); timestamp = attribute != null ? attribute.getValueLong() : null; @@ -82,19 +85,62 @@ public class Route extends GeoPath{ return Collections.unmodifiableList(propertiesList); } + /** + * Returns the route timestamp. + * + * @return Route timestamp + */ public Long getTimestamp() { return timestamp; } - + + /** + * Gets the route waypoint attributes from the map and creates the list of + * route waypoints. + * + * @param artifact Route artifact + * @param attributeMap Map of artifact attributes + * + * @throws GeoLocationDataException + */ + @Messages({ + "Route_point_label=Route point for route" + }) + private void createRoute(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException { + BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS); + + String label = getLabel(); + if (label == null || label.isEmpty()) { + label = Bundle.Route_point_label(); + } else { + label = String.format("%s: %s", Bundle.Route_point_label(), label); + } + + if (attribute != null) { + String value = attribute.getValueString(); + List waypointList = GeoWaypoints.deserializePoints(value); + + for (GeoWaypoint waypoint : waypointList) { + addToPath(new Waypoint(artifact, label, null, waypoint.getLatitude(), waypoint.getLongitude(), waypoint.getAltitude(), null, attributeMap, this)); + } + } else { + Waypoint start = getRouteStartPoint(artifact, attributeMap); + Waypoint end = getRouteEndPoint(artifact, attributeMap); + + addToPath(start); + addToPath(end); + } + } + /** * Get the route start point. * * @param artifact * @param attributeMap Map of artifact attributes for this waypoint. - * + * * An exception will be thrown if longitude or latitude is null. * - * @return Start waypoint + * @return Start waypoint * * @throws GeoLocationDataException. */ @@ -106,16 +152,14 @@ public class Route extends GeoPath{ BlackboardAttribute latitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START); BlackboardAttribute longitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START); BlackboardAttribute altitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE); - BlackboardAttribute pointTimestamp = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME); if (latitude != null && longitude != null) { - return new Waypoint(artifact, - Bundle.Route_Start_Label(), - pointTimestamp != null ? pointTimestamp.getValueLong() : null, - latitude.getValueDouble(), + return new RoutePoint(artifact, + Bundle.Route_Start_Label(), + latitude.getValueDouble(), longitude.getValueDouble(), altitude != null ? altitude.getValueDouble() : null, - null, attributeMap, this); + attributeMap); } else { throw new GeoLocationDataException("Unable to create route start point, invalid longitude and/or latitude"); } @@ -123,8 +167,8 @@ public class Route extends GeoPath{ /** * Get the route End point. - * - * An exception will be thrown if longitude or latitude is null. + * + * An exception will be thrown if longitude or latitude is null. * * @param attributeMap Map of artifact attributes for this waypoint * @@ -139,19 +183,52 @@ public class Route extends GeoPath{ BlackboardAttribute latitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END); BlackboardAttribute longitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END); BlackboardAttribute altitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE); - BlackboardAttribute pointTimestamp = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME); if (latitude != null && longitude != null) { - return new Waypoint(artifact, - Bundle.Route_End_Label(), - pointTimestamp != null ? pointTimestamp.getValueLong() : null, - latitude.getValueDouble(), + return new RoutePoint(artifact, + Bundle.Route_End_Label(), + latitude.getValueDouble(), longitude.getValueDouble(), altitude != null ? altitude.getValueDouble() : null, - null, attributeMap, this); + attributeMap); } else { throw new GeoLocationDataException("Unable to create route end point, invalid longitude and/or latitude"); } } + + /** + * Route waypoint specific implementation of Waypoint. + */ + private class RoutePoint extends Waypoint { + + /** + * Construct a RoutePoint + * + * @param artifact BlackboardArtifact for this waypoint + * @param label String waypoint label + * @param latitude Double waypoint latitude + * @param longitude Double waypoint longitude + * + * @param attributeMap A Map of attributes for the given artifact + * + * @throws GeoLocationDataException + */ + RoutePoint(BlackboardArtifact artifact, String label, Double latitude, Double longitude, Double altitude, Map attributeMap) throws GeoLocationDataException { + super(artifact, + label, + null, + latitude, + longitude, + altitude, + null, + attributeMap, + Route.this); + } + + @Override + public Long getTimestamp() { + return ((Route) getParentGeoPath()).getTimestamp(); + } + } } diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java index acc9e89352..f0ec1e50d3 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Waypoint.java @@ -43,7 +43,7 @@ public class Waypoint { final private String label; final private AbstractFile image; final private BlackboardArtifact artifact; - final private GeoPath path; + final private GeoPath parentGeoPath; final private List propertiesList; @@ -78,7 +78,7 @@ public class Waypoint { * @throws GeoLocationDataException Exception will be thrown if artifact did * not have a valid longitude and latitude. */ - Waypoint(BlackboardArtifact artifact, String label, Long timestamp, Double latitude, Double longitude, Double altitude, AbstractFile image, Map attributeMap, GeoPath path) throws GeoLocationDataException { + Waypoint(BlackboardArtifact artifact, String label, Long timestamp, Double latitude, Double longitude, Double altitude, AbstractFile image, Map attributeMap, GeoPath parentGeoPath) throws GeoLocationDataException { if (longitude == null || latitude == null) { throw new GeoLocationDataException("Invalid waypoint, null value passed for longitude or latitude"); } @@ -90,7 +90,7 @@ public class Waypoint { this.longitude = longitude; this.latitude = latitude; this.altitude = altitude; - this.path = path; + this.parentGeoPath = parentGeoPath; propertiesList = createGeolocationProperties(attributeMap); } @@ -173,13 +173,13 @@ public class Waypoint { } /** - * Returns the route that this waypoint is apart of . + * Returns the GeoPath that this waypoint is apart of . * * @return The waypoint route or null if the waypoint is not apart of a * route. */ - public GeoPath getPath() { - return path; + public GeoPath getParentGeoPath() { + return parentGeoPath; } /** @@ -231,6 +231,10 @@ public class Waypoint { } for (BlackboardAttribute.ATTRIBUTE_TYPE type : keys) { + // Don't add JSON properties to this list. + if (type.getValueType() == BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON) { + continue; + } String key = type.getDisplayName(); String value = attributeMap.get(type).getDisplayString(); diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java index 708b3a4803..12ca055a1c 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/WaypointBuilder.java @@ -39,39 +39,49 @@ import org.sleuthkit.datamodel.DataSource; public final class WaypointBuilder { private static final Logger logger = Logger.getLogger(WaypointBuilder.class.getName()); + + private final static String TIME_TYPE_IDS = String.format("%d, %d", + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()); + + private final static String GEO_ATTRIBUTE_TYPE_IDS = String.format("%d, %d, %d", + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS.getTypeID()); - // SELECT statement for getting a list of waypoints. - final static String GEO_ARTIFACT_QUERY + // SELECT statement for getting a list of waypoints where %s is a comma separated list + // of attribute type ids. + private final static String GEO_ARTIFACT_QUERY = "SELECT artifact_id, artifact_type_id " + "FROM blackboard_attributes " - + "WHERE attribute_type_id IN (%d, %d) "; //NON-NLS + + "WHERE attribute_type_id IN (%s) "; //NON-NLS // SELECT statement to get only artifact_ids - final static String GEO_ARTIFACT_QUERY_ID_ONLY + private final static String GEO_ARTIFACT_QUERY_ID_ONLY = "SELECT artifact_id " + "FROM blackboard_attributes " - + "WHERE attribute_type_id IN (%d, %d) "; //NON-NLS + + "WHERE attribute_type_id IN (%s) "; //NON-NLS // This Query will return a list of waypoint artifacts - final static String GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY + private final static String GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY = "SELECT blackboard_attributes.artifact_id " + "FROM blackboard_attributes, blackboard_artifacts " + "WHERE blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id " - + "AND blackboard_attributes.attribute_type_id IN(%d, %d) " + + "AND blackboard_attributes.attribute_type_id IN(%s) " + "AND data_source_obj_id IN (%s)"; //NON-NLS // Select will return the "most recent" timestamp from all waypoings - final static String MOST_RECENT_TIME + private final static String MOST_RECENT_TIME = "SELECT MAX(value_int64) - (%d * 86400)" //86400 is the number of seconds in a day. + "FROM blackboard_attributes " - + "WHERE attribute_type_id IN(%d, %d) " + + "WHERE attribute_type_id IN(%s) " + "AND artifact_id " + "IN ( " + "%s" //GEO_ARTIFACT with or without data source + " )"; // Returns a list of artifacts with no time stamp - final static String SELECT_WO_TIMESTAMP + private final static String SELECT_WO_TIMESTAMP = "SELECT DISTINCT artifact_id, artifact_type_id " + "FROM blackboard_attributes " + "WHERE artifact_id NOT IN (%s) " @@ -132,7 +142,7 @@ public final class WaypointBuilder { public static List getRoutes(List waypoints) { List routeList = new ArrayList<>(); for (Waypoint point : waypoints) { - GeoPath path = point.getPath(); + GeoPath path = point.getParentGeoPath(); if (path instanceof Route) { Route route = (Route) path; if (!routeList.contains(route)) { @@ -154,7 +164,7 @@ public final class WaypointBuilder { public static List getTracks(List waypoints) { List trackList = new ArrayList<>(); for (Waypoint point : waypoints) { - GeoPath path = point.getPath(); + GeoPath path = point.getParentGeoPath(); if (path instanceof Track) { Track route = (Track) path; if (!trackList.contains(route)) { @@ -506,9 +516,7 @@ public final class WaypointBuilder { // FROM blackboard_attributes // WHERE attribute_type_id IN (%d, %d) return String.format(SELECT_WO_TIMESTAMP, - String.format(GEO_ARTIFACT_QUERY_ID_ONLY, - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()), + String.format(GEO_ARTIFACT_QUERY_ID_ONLY,TIME_TYPE_IDS), getWaypointListQuery(dataSources)); } @@ -541,15 +549,13 @@ public final class WaypointBuilder { // MOST_RECENT_TIME // SELECT MAX(value_int64) - (%d * 86400) // FROM blackboard_attributes -// WHERE attribute_type_id IN(%d, %d) +// WHERE attribute_type_id IN(%s) // AND artifact_id // IN ( %s ) // mostRecentQuery = String.format("AND value_int64 > (%s)", //NON-NLS String.format(MOST_RECENT_TIME, - cntDaysFromRecent, - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID(), + cntDaysFromRecent, TIME_TYPE_IDS, getWaypointListQuery(dataSources) )); } @@ -557,10 +563,8 @@ public final class WaypointBuilder { // GEO_ARTIFACT_QUERY // SELECT artifact_id, artifact_type_id // FROM blackboard_attributes -// WHERE attribute_type_id IN (%d, %d) - String query = String.format(GEO_ARTIFACT_QUERY, - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED.getTypeID()); +// WHERE attribute_type_id IN (%s) + String query = String.format(GEO_ARTIFACT_QUERY, TIME_TYPE_IDS); // That are in the list of artifacts for the given data Sources query += String.format("AND artifact_id IN(%s)", getWaypointListQuery(dataSources)); //NON-NLS @@ -591,10 +595,8 @@ public final class WaypointBuilder { // GEO_ARTIFACT_QUERY // SELECT artifact_id, artifact_type_id // FROM blackboard_attributes -// WHERE attribute_type_id IN (%d, %d) - return String.format(GEO_ARTIFACT_QUERY, - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID()); +// WHERE attribute_type_id IN (%s) + return String.format(GEO_ARTIFACT_QUERY, GEO_ATTRIBUTE_TYPE_IDS); } String dataSourceList = ""; @@ -607,9 +609,7 @@ public final class WaypointBuilder { dataSourceList = dataSourceList.substring(0, dataSourceList.length() - 1); } - return String.format(GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY, - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), - BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), + return String.format(GEO_ARTIFACT_WITH_DATA_SOURCES_QUERY, GEO_ATTRIBUTE_TYPE_IDS, dataSourceList); } diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index d17162fb65..17522c576c 100644 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -41,6 +41,7 @@ from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException +from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper import traceback import general @@ -52,15 +53,25 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): def __init__(self): self._logger = Logger.getLogger(self.__class__.__name__) + self.current_case = None + self.PROGRAM_NAME = "Google Maps History" + self.CAT_DESTINATION = "Destination" def analyze(self, dataSource, fileManager, context): + try: + self.current_case = Case.getCurrentCaseThrows() + except NoCurrentCaseException as ex: + self._logger.log(Level.WARNING, "No case currently open.", ex) + self._logger.log(Level.WARNING, traceback.format_exc()) + return + try: absFiles = fileManager.findFiles(dataSource, "da_destination_history") if absFiles.isEmpty(): return for abstractFile in absFiles: try: - jFile = File(Case.getCurrentCase().getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) + jFile = File(self.current_case.getTempDirectory(), str(abstractFile.getId()) + abstractFile.getName()) ContentUtils.writeToFile(abstractFile, jFile, context.dataSourceIngestIsCancelled) self.__findGeoLocationsInDB(jFile.toString(), abstractFile) except Exception as ex: @@ -75,6 +86,8 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): return try: + artifactHelper = GeoArtifactsHelper(self.current_case.getSleuthkitCase(), + general.MODULE_NAME, abstractFile) Class.forName("org.sqlite.JDBC") # load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) statement = connection.createStatement() @@ -100,32 +113,18 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): dest_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("dest_lng")) source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat")) source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng")) - - attributes = ArrayList() - artifact = abstractFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_CATEGORY, general.MODULE_NAME, "Destination")) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, general.MODULE_NAME, time)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END, general.MODULE_NAME, dest_lat)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END, general.MODULE_NAME, dest_lng)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START, general.MODULE_NAME, source_lat)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START, general.MODULE_NAME, source_lng)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, general.MODULE_NAME, dest_title)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_LOCATION, general.MODULE_NAME, dest_address)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME, general.MODULE_NAME, "Google Maps History")) - - artifact.addAttributes(attributes) - try: - # index the artifact for keyword search - blackboard = Case.getCurrentCase().getSleuthkitCase().getBlackboard() - blackboard.postArtifact(artifact, general.MODULE_NAME) - except Blackboard.BlackboardException as ex: - self._logger.log(Level.SEVERE, "Unable to index blackboard artifact " + str(artifact.getArtifactID()), ex) - self._logger.log(Level.SEVERE, traceback.format_exc()) - MessageNotifyUtil.Notify.error("Failed to index GPS route artifact for keyword search.", artifact.getDisplayName()) + + artifactHelper.addRoute(dest_title, time, dest_address, self.PROGRAM_NAME, self.CAT_DESTINATION, source_lat, source_lng, dest_lat, dest_lng) except SQLException as ex: # Unable to execute Google map locations SQL query against database. pass + except TskCoreException as ex: + self._logger.log(Level.SEVERE, "Failed to add route artifacts.", ex) + self._logger.log(Level.SEVERE, traceback.format_exc()) + except BlackboardException as ex: + self._logger.log(Level.WARNING, "Failed to post artifacts.", ex) + self._logger.log(Level.WARNING, traceback.format_exc()) except Exception as ex: self._logger.log(Level.SEVERE, "Error processing google maps history.", ex) self._logger.log(Level.SEVERE, traceback.format_exc()) From e6b01d43e53fde77545feacef90499b61bd11337 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 6 Feb 2020 17:05:16 -0500 Subject: [PATCH 03/77] Remove unused import --- Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index 4181d96d14..e8991005b2 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -25,7 +25,6 @@ import java.util.Map; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.GeoWaypoints; import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint; From e4dac1cb90d83559016338175e39d4481ec8f404 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 7 Feb 2020 09:48:44 -0500 Subject: [PATCH 04/77] Added geolocation .properties changes --- .../autopsy/geolocation/datamodel/Bundle.properties-MERGED | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED index 93f9329d9a..649f580627 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED @@ -3,7 +3,7 @@ GEOTrack_point_label_header=Trackpoint for track: {0} LastKnownWaypoint_Label=Last Known Location Route_End_Label=End Route_Label=As-the-crow-flies Route -Route_point_label=Route point +Route_point_label=Route point for route Route_Start_Label=Start SearchWaypoint_DisplayLabel=GPS Search TrackpointWaypoint_DisplayLabel=GPS Trackpoint From f67c3cdbe53769aca782089848212ab629b60410 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 7 Feb 2020 13:06:09 -0500 Subject: [PATCH 05/77] Updated based on review comments --- .../autopsy/geolocation/datamodel/Bundle.properties-MERGED | 2 +- .../org/sleuthkit/autopsy/geolocation/datamodel/Route.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED index 649f580627..18627193b9 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED @@ -3,7 +3,7 @@ GEOTrack_point_label_header=Trackpoint for track: {0} LastKnownWaypoint_Label=Last Known Location Route_End_Label=End Route_Label=As-the-crow-flies Route -Route_point_label=Route point for route +Route_point_label=Waypoints for route Route_Start_Label=Start SearchWaypoint_DisplayLabel=GPS Search TrackpointWaypoint_DisplayLabel=GPS Trackpoint diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index e8991005b2..4e23ffaf14 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -31,7 +31,7 @@ import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint; /** * A Route represents a TSK_GPS_ROUTE artifact which has a start and end point * however the class was written with the assumption that routes may have more - * that two points. + * than two points. * */ public class Route extends GeoPath { @@ -103,7 +103,7 @@ public class Route extends GeoPath { * @throws GeoLocationDataException */ @Messages({ - "Route_point_label=Route point for route" + "Route_point_label=Waypoints for route" }) private void createRoute(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException { BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_WAYPOINTS); From 5f9eccc1b28ad6792ee1016bef4fe28a1f54cf29 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 11 Feb 2020 18:19:47 -0500 Subject: [PATCH 06/77] Update guava version in KWS project.xml --- KeywordSearch/nbproject/project.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/KeywordSearch/nbproject/project.xml b/KeywordSearch/nbproject/project.xml index 25e05e30fa..2de991d105 100644 --- a/KeywordSearch/nbproject/project.xml +++ b/KeywordSearch/nbproject/project.xml @@ -276,8 +276,8 @@ release/modules/ext/icu4j-3.8.jar - ext/guava-17.0.jar - release/modules/ext/guava-17.0.jar + ext/guava-19.0.jar + release/modules/ext/guava-19.0.jar ext/language-detector-0.6.jar From 7dcaa72f7842dadc2adc4dbd42bb12a4055fe70a Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Thu, 13 Feb 2020 12:14:52 -0500 Subject: [PATCH 07/77] updated default for flag previous devices --- .../centralrepository/ingestmodule/CentralRepoIngestModule.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java index ec00dffe88..e561aeeff6 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/ingestmodule/CentralRepoIngestModule.java @@ -67,7 +67,7 @@ final class CentralRepoIngestModule implements FileIngestModule { private static final String MODULE_NAME = CentralRepoIngestModuleFactory.getModuleName(); static final boolean DEFAULT_FLAG_TAGGED_NOTABLE_ITEMS = true; - static final boolean DEFAULT_FLAG_PREVIOUS_DEVICES = true; + static final boolean DEFAULT_FLAG_PREVIOUS_DEVICES = false; static final boolean DEFAULT_CREATE_CR_PROPERTIES = true; private final static Logger logger = Logger.getLogger(CentralRepoIngestModule.class.getName()); From 79fda8405055115823a515d4e9e4c7e40b8c5d82 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Thu, 13 Feb 2020 17:37:55 -0500 Subject: [PATCH 08/77] refactoring in EamDbSettingsDialog --- .../datamodel/CentralRepoDbUtil.java | 6 +- .../optionspanel/CentralRepoDbManager.java | 351 ++++++++++++++++++ .../optionspanel/EamDbSettingsDialog.form | 4 +- .../optionspanel/EamDbSettingsDialog.java | 281 ++------------ 4 files changed, 399 insertions(+), 243 deletions(-) create mode 100755 Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java index 4ba8ac579e..4cf0d8af67 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java @@ -31,6 +31,7 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationService.Coordinatio import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo.SOFTWARE_CR_DB_SCHEMA_VERSION; +import org.sleuthkit.autopsy.centralrepository.optionspanel.EamDbSettingsDialog; /** * @@ -177,8 +178,11 @@ public class CentralRepoDbUtil { "EamDbUtil.exclusiveLockAquisitionFailure.message=Unable to acquire exclusive lock for Central Repository."}) public static void upgradeDatabase() throws CentralRepoException { if (!CentralRepository.isEnabled()) { - return; + EamDbSettingsDialog dialog = new EamDbSettingsDialog(); + dialog. + promptUserForSetup(); } + CentralRepository db = null; CoordinationService.Lock lock = null; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java new file mode 100755 index 0000000000..bd1d52b1f0 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java @@ -0,0 +1,351 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.centralrepository.optionspanel; + +import java.awt.Cursor; +import java.io.File; +import java.util.logging.Level; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import org.openide.util.NbBundle; +import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatforms; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings; +import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; +import org.sleuthkit.autopsy.centralrepository.optionspanel.DatabaseTestResult; +import org.sleuthkit.autopsy.coreutils.Logger; + + +public class CentralRepoDbManager { + private static final String CENTRAL_REPO_DB_NAME = "central_repository"; + private static final String CENTRAL_REPO_SQLITE_EXT = ".db"; + + private static final Logger logger = Logger.getLogger(CentralRepoDbManager.class.getName()); + + private DatabaseTestResult testingStatus; + private CentralRepoPlatforms selectedPlatform; + + private PostgresCentralRepoSettings dbSettingsPostgres; + private SqliteCentralRepoSettings dbSettingsSqlite; + + private boolean configurationChanged = false; + + + public CentralRepoDbManager() { + dbSettingsPostgres = new PostgresCentralRepoSettings(); + dbSettingsSqlite = new SqliteCentralRepoSettings(); + selectedPlatform = CentralRepoPlatforms.getSelectedPlatform(); + if (selectedPlatform == null || selectedPlatform.equals(CentralRepoPlatforms.DISABLED)) { + selectedPlatform = CentralRepoPlatforms.POSTGRESQL; + } + } + + /** + * prompts user based on testing status (i.e. failure to connect, invalid schema, db does not exist, etc.) + * @param warnDoesNotExist whether or not to prompt the user should the database not exist (otherwise silently create the db) + * @return whether or not the ultimate status after prompts is okay to continue + */ + @NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", + "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", + "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", + "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?", + "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed", + "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again."}) + private boolean promptTestStatusWarnings(boolean warnDoesNotExist) { + if (testingStatus == DatabaseTestResult.CONNECTION_FAILED) { + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(), + Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(), + JOptionPane.WARNING_MESSAGE); + } else if (testingStatus == DatabaseTestResult.SCHEMA_INVALID) { + // There's an existing database or file, but it's not in our format. + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(), + Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(), + JOptionPane.WARNING_MESSAGE); + } else if (testingStatus == DatabaseTestResult.DB_DOES_NOT_EXIST) { + //database doesn't exist do you want to create + boolean createDb = (!warnDoesNotExist || + JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(), + Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(), + JOptionPane.YES_NO_OPTION)); + + if (createDb) + createDb(); + } + + return (testingStatus == DatabaseTestResult.TESTEDOK); + } + + + + + + + @NbBundle.Messages({"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database", + "EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.", + "EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again."}) + private boolean createDb() { + boolean result = false; + boolean dbCreated = true; + switch (selectedPlatform) { + case POSTGRESQL: + if (!dbSettingsPostgres.verifyDatabaseExists()) { + dbCreated = dbSettingsPostgres.createDatabase(); + } + if (dbCreated) { + result = dbSettingsPostgres.initializeDatabaseSchema() + && dbSettingsPostgres.insertDefaultDatabaseContent(); + } + if (!result) { + // Remove the incomplete database + if (dbCreated) { + dbSettingsPostgres.deleteDatabase(); + } + + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_createPostgresDbError_message(), + Bundle.EamDbSettingsDialog_okButton_createDbError_title(), + JOptionPane.WARNING_MESSAGE); + logger.severe("Unable to initialize database schema or insert contents into central repository."); + return false; + } + break; + case SQLITE: + if (!dbSettingsSqlite.dbDirectoryExists()) { + dbCreated = dbSettingsSqlite.createDbDirectory(); + } + if (dbCreated) { + result = dbSettingsSqlite.initializeDatabaseSchema() + && dbSettingsSqlite.insertDefaultDatabaseContent(); + } + if (!result) { + if (dbCreated) { + dbSettingsSqlite.deleteDatabase(); + } + + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_createSQLiteDbError_message(), + Bundle.EamDbSettingsDialog_okButton_createDbError_title(), + JOptionPane.WARNING_MESSAGE); + logger.severe("Unable to initialize database schema or insert contents into central repository."); + return false; + } + break; + } + testingStatus = DatabaseTestResult.TESTEDOK; + return true; + } + + + /** + * saves a new central repository based on current settings + */ + @NbBundle.Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.", + "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.", + "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database."}) + private void saveNewCentralRepo() { + /** + * We have to shutdown the previous platform's connection pool first; + * assuming it wasn't DISABLED. This will close any existing idle + * connections. + * + * The next use of an EamDb API method will start a new connection pool + * using those new settings. + */ + try { + CentralRepository previousDbManager = CentralRepository.getInstance(); + if (null != previousDbManager) { + // NOTE: do not set/save the seleted platform before calling this. + CentralRepository.getInstance().shutdownConnections(); + } + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Failed to close database connections in previously selected platform.", ex); // NON-NLS + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(this, + Bundle.EamDbSettingsDialog_okButton_errorMsg_text(), + Bundle.EamDbSettingsDialog_okButton_errorTitle_text(), + JOptionPane.WARNING_MESSAGE); + }); + } + + // Even if we fail to close the existing connections, make sure that we + // save the new connection settings, so an Autopsy restart will correctly + // start with the new settings. + CentralRepoPlatforms.setSelectedPlatform(selectedPlatform.name()); + CentralRepoPlatforms.saveSelectedPlatform(); + + switch (selectedPlatform) { + case POSTGRESQL: + // save the new PostgreSQL settings + dbSettingsPostgres.saveSettings(); + // Load those newly saved settings into the postgres db manager instance + // in case we are still using the same instance. + try { + CentralRepository.getInstance().updateSettings(); + configurationChanged = true; + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex); //NON-NLS + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + return; + } + + break; + case SQLITE: + // save the new SQLite settings + dbSettingsSqlite.saveSettings(); + // Load those newly saved settings into the sqlite db manager instance + // in case we are still using the same instance. + try { + CentralRepository.getInstance().updateSettings(); + configurationChanged = true; + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex); //NON-NLS + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + return; + } + break; + case DISABLED: + break; + } + } + + + static class DatabaseSettingsValidResult { + private final String errorMessage; + private final boolean success; + + public DatabaseSettingsValidResult(String errorMessage, boolean success) { + this.errorMessage = errorMessage; + this.success = success; + } + + public String getErrorMessage() { + return errorMessage; + } + + public boolean isSuccess() { + return success; + } + } + + + /** + * Tests whether or not the database settings are valid. + * + * @return True or false. + */ + private DatabaseSettingsValidResult databaseSettingsAreValid( + String tbDbHostname, Integer tbDbPort, String tbDbUsername, String tfDatabasePath, String jpDbPassword) { + + boolean result = true; + StringBuilder guidanceText = new StringBuilder(); + + switch (selectedPlatform) { + case POSTGRESQL: + try { + dbSettingsPostgres.setHost(tbDbHostname); + } catch (CentralRepoException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setPort(tbDbPort); + } catch (NumberFormatException | CentralRepoException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setDbName(CENTRAL_REPO_DB_NAME); + } catch (CentralRepoException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setUserName(tbDbUsername); + } catch (CentralRepoException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + + try { + dbSettingsPostgres.setPassword(jpDbPassword); + } catch (CentralRepoException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + break; + case SQLITE: + try { + File databasePath = new File(tfDatabasePath); + dbSettingsSqlite.setDbName(CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT); + dbSettingsSqlite.setDbDirectory(databasePath.getPath()); + } catch (CentralRepoException ex) { + guidanceText.append(ex.getMessage()); + result = false; + } + break; + } + + return new DatabaseSettingsValidResult(guidanceText.toString(), result); + } + + + private DatabaseTestResult testDbSettings() { + switch (selectedPlatform) { + case POSTGRESQL: + if (dbSettingsPostgres.verifyConnection()) { + if (dbSettingsPostgres.verifyDatabaseExists()) { + if (dbSettingsPostgres.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; + } + } else { + testingStatus = DatabaseTestResult.CONNECTION_FAILED; + } + break; + case SQLITE: + if (dbSettingsSqlite.dbFileExists()) { + if (dbSettingsSqlite.verifyConnection()) { + if (dbSettingsSqlite.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; + } + break; + } + + return testingStatus; + } + + + /** + * Returns if changes to the central repository configuration were + * successfully applied + * + * @return true if the database configuration was successfully changed false + * if it was not + */ + boolean wasConfigurationChanged() { + return configurationChanged; + } +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form index 0f39326bec..27eae7629c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.form @@ -133,7 +133,7 @@ - + @@ -410,4 +410,4 @@ - \ No newline at end of file + diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 271a8a4f04..4bd17b561e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -45,6 +45,7 @@ import static org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatf import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings; import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.centralrepository.optionspanel.DatabaseTestResult; /** * Configuration dialog for Central Repository database settings. @@ -53,17 +54,15 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; public class EamDbSettingsDialog extends JDialog { private static final Logger logger = Logger.getLogger(EamDbSettingsDialog.class.getName()); - private static final String CENTRAL_REPO_DB_NAME = "central_repository"; - private static final String CENTRAL_REPO_SQLITE_EXT = ".db"; + private static final long serialVersionUID = 1L; private final Collection textBoxes; private final TextBoxChangedListener textBoxChangedListener; - private final PostgresCentralRepoSettings dbSettingsPostgres; - private final SqliteCentralRepoSettings dbSettingsSqlite; - private DatabaseTestResult testingStatus; - private CentralRepoPlatforms selectedPlatform; - private boolean configurationChanged = false; + + + + /** * Creates new form EamDbSettingsDialog @@ -80,12 +79,6 @@ public class EamDbSettingsDialog extends JDialog { textBoxes = new ArrayList<>(); textBoxChangedListener = new TextBoxChangedListener(); - dbSettingsPostgres = new PostgresCentralRepoSettings(); - dbSettingsSqlite = new SqliteCentralRepoSettings(); - selectedPlatform = CentralRepoPlatforms.getSelectedPlatform(); - if (selectedPlatform == null || selectedPlatform.equals(CentralRepoPlatforms.DISABLED)) { - selectedPlatform = CentralRepoPlatforms.POSTGRESQL; - } initComponents(); fcDatabasePath.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); @@ -398,215 +391,27 @@ public class EamDbSettingsDialog extends JDialog { } }//GEN-LAST:event_bnDatabasePathFileOpenActionPerformed - private void testDbSettings() { - switch (selectedPlatform) { - case POSTGRESQL: - if (dbSettingsPostgres.verifyConnection()) { - if (dbSettingsPostgres.verifyDatabaseExists()) { - if (dbSettingsPostgres.verifyDatabaseSchema()) { - testingStatus = DatabaseTestResult.TESTEDOK; - } else { - testingStatus = DatabaseTestResult.SCHEMA_INVALID; - } - } else { - testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; - } - } else { - testingStatus = DatabaseTestResult.CONNECTION_FAILED; - } - break; - case SQLITE: - if (dbSettingsSqlite.dbFileExists()) { - if (dbSettingsSqlite.verifyConnection()) { - if (dbSettingsSqlite.verifyDatabaseSchema()) { - testingStatus = DatabaseTestResult.TESTEDOK; - } else { - testingStatus = DatabaseTestResult.SCHEMA_INVALID; - } - } else { - testingStatus = DatabaseTestResult.SCHEMA_INVALID; - } - } else { - testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; - } - break; - } - valid(); - } - @Messages({"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database", - "EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.", - "EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again."}) - private void createDb() { - boolean result = false; - boolean dbCreated = true; - switch (selectedPlatform) { - case POSTGRESQL: - if (!dbSettingsPostgres.verifyDatabaseExists()) { - dbCreated = dbSettingsPostgres.createDatabase(); - } - if (dbCreated) { - result = dbSettingsPostgres.initializeDatabaseSchema() - && dbSettingsPostgres.insertDefaultDatabaseContent(); - } - if (!result) { - // Remove the incomplete database - if (dbCreated) { - dbSettingsPostgres.deleteDatabase(); - } - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createPostgresDbError_message(), - Bundle.EamDbSettingsDialog_okButton_createDbError_title(), - JOptionPane.WARNING_MESSAGE); - logger.severe("Unable to initialize database schema or insert contents into central repository."); - return; - } - break; - case SQLITE: - if (!dbSettingsSqlite.dbDirectoryExists()) { - dbCreated = dbSettingsSqlite.createDbDirectory(); - } - if (dbCreated) { - result = dbSettingsSqlite.initializeDatabaseSchema() - && dbSettingsSqlite.insertDefaultDatabaseContent(); - } - if (!result) { - if (dbCreated) { - dbSettingsSqlite.deleteDatabase(); - } - - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createSQLiteDbError_message(), - Bundle.EamDbSettingsDialog_okButton_createDbError_title(), - JOptionPane.WARNING_MESSAGE); - logger.severe("Unable to initialize database schema or insert contents into central repository."); - return; - } - break; - } - testingStatus = DatabaseTestResult.TESTEDOK; - valid(); - } - - /** - * Returns if changes to the central repository configuration were - * successfully applied - * - * @return true if the database configuration was successfully changed false - * if it was not - */ - boolean wasConfigurationChanged() { - return configurationChanged; - } - - @Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.", - "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.", - "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database.", - "EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", - "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", - "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", - "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?", - "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed", - "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again."}) private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); testDbSettings(); - if (testingStatus == DatabaseTestResult.CONNECTION_FAILED) { - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(), - Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(), - JOptionPane.WARNING_MESSAGE); - } else if (testingStatus == DatabaseTestResult.SCHEMA_INVALID) { - // There's an existing database or file, but it's not in our format. - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(), - Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(), - JOptionPane.WARNING_MESSAGE); - } else if (testingStatus == DatabaseTestResult.DB_DOES_NOT_EXIST) { - //database doesn't exist do you want to create - if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(), - Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(), - JOptionPane.YES_NO_OPTION)) { - createDb(); - } - } - if (testingStatus != DatabaseTestResult.TESTEDOK) { + boolean testedOk = promptTestStatusWarnings(true); + if (!testedOk) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); return; } - - /** - * We have to shutdown the previous platform's connection pool first; - * assuming it wasn't DISABLED. This will close any existing idle - * connections. - * - * The next use of an EamDb API method will start a new connection pool - * using those new settings. - */ - try { - CentralRepository previousDbManager = CentralRepository.getInstance(); - if (null != previousDbManager) { - // NOTE: do not set/save the seleted platform before calling this. - CentralRepository.getInstance().shutdownConnections(); - } - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Failed to close database connections in previously selected platform.", ex); // NON-NLS - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(this, - Bundle.EamDbSettingsDialog_okButton_errorMsg_text(), - Bundle.EamDbSettingsDialog_okButton_errorTitle_text(), - JOptionPane.WARNING_MESSAGE); - }); - } - - // Even if we fail to close the existing connections, make sure that we - // save the new connection settings, so an Autopsy restart will correctly - // start with the new settings. - CentralRepoPlatforms.setSelectedPlatform(selectedPlatform.name()); - CentralRepoPlatforms.saveSelectedPlatform(); - - switch (selectedPlatform) { - case POSTGRESQL: - // save the new PostgreSQL settings - dbSettingsPostgres.saveSettings(); - // Load those newly saved settings into the postgres db manager instance - // in case we are still using the same instance. - try { - CentralRepository.getInstance().updateSettings(); - configurationChanged = true; - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex); //NON-NLS - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - return; - } - - break; - case SQLITE: - // save the new SQLite settings - dbSettingsSqlite.saveSettings(); - // Load those newly saved settings into the sqlite db manager instance - // in case we are still using the same instance. - try { - CentralRepository.getInstance().updateSettings(); - configurationChanged = true; - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex); //NON-NLS - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); - return; - } - break; - case DISABLED: - break; - } + + saveNewCentralRepo(); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); dispose(); }//GEN-LAST:event_bnOkActionPerformed + + private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed dispose(); }//GEN-LAST:event_bnCancelActionPerformed @@ -757,6 +562,35 @@ public class EamDbSettingsDialog extends JDialog { && databaseSettingsAreValid(); } + + /** + * Validates that the form is filled out correctly for our usage. + * + * @return true if it's okay, false otherwise. + */ + private boolean valid() { + return enableOkButton(checkFields()); + } + + /** + * Enable the "OK" button if the db test passed. Disabled defaults to db + * test passed. + * + * @return true + */ + @Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a different database type."}) + private boolean enableOkButton(boolean isValidInput) { + if (isValidInput) { + bnOk.setEnabled(true); + } else { + bnOk.setEnabled(false); + } + return true; + + } + + + /** * Tests whether or not the database settings are valid. * @@ -818,32 +652,6 @@ public class EamDbSettingsDialog extends JDialog { return result; } - /** - * Validates that the form is filled out correctly for our usage. - * - * @return true if it's okay, false otherwise. - */ - private boolean valid() { - return enableOkButton(checkFields()); - } - - /** - * Enable the "OK" button if the db test passed. Disabled defaults to db - * test passed. - * - * @return true - */ - @Messages({"EamDbSettingsDialog.validation.finished=Click OK to save your database settings and return to the Options. Or select a different database type."}) - private boolean enableOkButton(boolean isValidInput) { - if (isValidInput) { - bnOk.setEnabled(true); - } else { - bnOk.setEnabled(false); - } - return true; - - } - /** * Used to listen for changes in text boxes. It lets the panel know things * have been updated and that validation needs to happen. @@ -876,13 +684,6 @@ public class EamDbSettingsDialog extends JDialog { } } - private enum DatabaseTestResult { - UNTESTED, - CONNECTION_FAILED, - SCHEMA_INVALID, - DB_DOES_NOT_EXIST, - TESTEDOK; - } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JButton bnCancel; From f13160df2e9eb6892bb5afc8d8a6d8cfe8257287 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Thu, 13 Feb 2020 17:39:12 -0500 Subject: [PATCH 09/77] adding DatabaseTestResult --- .../optionspanel/DatabaseTestResult.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100755 Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java new file mode 100755 index 0000000000..f936e6af55 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java @@ -0,0 +1,15 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package org.sleuthkit.autopsy.centralrepository.optionspanel; + +enum DatabaseTestResult { + UNTESTED, + CONNECTION_FAILED, + SCHEMA_INVALID, + DB_DOES_NOT_EXIST, + TESTEDOK; +} + From 5befaf6b21c4387f8491291220c62f7f08e76704 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Fri, 14 Feb 2020 09:14:14 -0500 Subject: [PATCH 10/77] continuing refactor of Central Repo Db Manager --- .../CentralRepoDbManager.java | 131 ++++++++++++------ .../datamodel/CentralRepoDbUtil.java | 81 ----------- .../DatabaseTestResult.java | 4 +- .../eventlisteners/Installer.java | 3 +- .../optionspanel/EamDbSettingsDialog.java | 51 ++++++- .../optionspanel/GlobalSettingsPanel.java | 3 +- 6 files changed, 137 insertions(+), 136 deletions(-) rename Core/src/org/sleuthkit/autopsy/centralrepository/{optionspanel => datamodel}/CentralRepoDbManager.java (70%) rename Core/src/org/sleuthkit/autopsy/centralrepository/{optionspanel => datamodel}/DatabaseTestResult.java (75%) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java similarity index 70% rename from Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java rename to Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index bd1d52b1f0..9a50b7f209 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -3,21 +3,18 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package org.sleuthkit.autopsy.centralrepository.optionspanel; +package org.sleuthkit.autopsy.centralrepository.datamodel; import java.awt.Cursor; import java.io.File; +import java.sql.SQLException; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatforms; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings; -import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; -import org.sleuthkit.autopsy.centralrepository.optionspanel.DatabaseTestResult; +import org.sleuthkit.autopsy.centralrepository.optionspanel.EamDbSettingsDialog; +import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; @@ -26,6 +23,80 @@ public class CentralRepoDbManager { private static final String CENTRAL_REPO_SQLITE_EXT = ".db"; private static final Logger logger = Logger.getLogger(CentralRepoDbManager.class.getName()); + + /** + * Upgrade the current Central Reposity schema to the newest version. If the + * upgrade fails, the Central Repository will be disabled and the current + * settings will be cleared. + */ + @NbBundle.Messages(value = {"EamDbUtil.centralRepoDisabled.message= The Central Repository has been disabled.", "EamDbUtil.centralRepoUpgradeFailed.message=Failed to upgrade Central Repository.", "EamDbUtil.centralRepoConnectionFailed.message=Unable to connect to Central Repository.", "EamDbUtil.exclusiveLockAquisitionFailure.message=Unable to acquire exclusive lock for Central Repository."}) + public static void upgradeDatabase() throws CentralRepoException { + if (!CentralRepository.isEnabled()) { + EamDbSettingsDialog dialog = new EamDbSettingsDialog(); + dialog.promptUserForSetup(); + } + CentralRepository db = null; + CoordinationService.Lock lock = null; + //get connection + try { + try { + db = CentralRepository.getInstance(); + } catch (CentralRepoException ex) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); + throw new CentralRepoException("Error updating central repository, unable to make connection", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } + //get lock necessary for upgrade + if (db != null) { + try { + // This may return null if locking isn't supported, which is fine. It will + // throw an exception if locking is supported but we can't get the lock + // (meaning the database is in use by another user) + lock = db.getExclusiveMultiUserDbLock(); + //perform upgrade + } catch (CentralRepoException ex) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); + throw new CentralRepoException("Error updating central repository, unable to acquire exclusive lock", Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } + try { + db.upgradeSchema(); + } catch (CentralRepoException ex) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository", ex); + throw new CentralRepoException("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } catch (SQLException ex) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository", ex); + throw new CentralRepoException("Error updating central repository", Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } catch (IncompatibleCentralRepoException ex) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository", ex); + throw new CentralRepoException("Error updating central repository", ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } finally { + if (lock != null) { + try { + lock.release(); + } catch (CoordinationService.CoordinationServiceException ex) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error releasing database lock", ex); + } + } + } + } else { + throw new CentralRepoException("Unable to connect to database", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message()); + } + } catch (CentralRepoException ex) { + // Disable the central repo and clear the current settings. + try { + if (null != CentralRepository.getInstance()) { + CentralRepository.getInstance().shutdownConnections(); + } + } catch (CentralRepoException ex2) { + CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error shutting down central repo connection pool", ex2); + } + CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.DISABLED.name()); + CentralRepoPlatforms.saveSelectedPlatform(); + throw ex; + } + } + + + private DatabaseTestResult testingStatus; private CentralRepoPlatforms selectedPlatform; @@ -45,43 +116,7 @@ public class CentralRepoDbManager { } } - /** - * prompts user based on testing status (i.e. failure to connect, invalid schema, db does not exist, etc.) - * @param warnDoesNotExist whether or not to prompt the user should the database not exist (otherwise silently create the db) - * @return whether or not the ultimate status after prompts is okay to continue - */ - @NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", - "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", - "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", - "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?", - "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed", - "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again."}) - private boolean promptTestStatusWarnings(boolean warnDoesNotExist) { - if (testingStatus == DatabaseTestResult.CONNECTION_FAILED) { - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(), - Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(), - JOptionPane.WARNING_MESSAGE); - } else if (testingStatus == DatabaseTestResult.SCHEMA_INVALID) { - // There's an existing database or file, but it's not in our format. - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(), - Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(), - JOptionPane.WARNING_MESSAGE); - } else if (testingStatus == DatabaseTestResult.DB_DOES_NOT_EXIST) { - //database doesn't exist do you want to create - boolean createDb = (!warnDoesNotExist || - JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(), - Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(), - JOptionPane.YES_NO_OPTION)); - - if (createDb) - createDb(); - } - return (testingStatus == DatabaseTestResult.TESTEDOK); - } @@ -91,7 +126,7 @@ public class CentralRepoDbManager { @NbBundle.Messages({"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database", "EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.", "EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again."}) - private boolean createDb() { + public boolean createDb() { boolean result = false; boolean dbCreated = true; switch (selectedPlatform) { @@ -215,6 +250,14 @@ public class CentralRepoDbManager { break; } } + + public DatabaseTestResult getStatus() { + throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + } + + public CentralRepoPlatforms getSelectedPlatform() { + return selectedPlatform; + } static class DatabaseSettingsValidResult { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java index 4cf0d8af67..60701b44e5 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbUtil.java @@ -25,13 +25,9 @@ import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.coordinationservice.CoordinationService; -import org.sleuthkit.autopsy.coordinationservice.CoordinationService.CoordinationServiceException; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo.SOFTWARE_CR_DB_SCHEMA_VERSION; -import org.sleuthkit.autopsy.centralrepository.optionspanel.EamDbSettingsDialog; /** * @@ -167,83 +163,6 @@ public class CentralRepoDbUtil { return true; } - /** - * Upgrade the current Central Reposity schema to the newest version. If the - * upgrade fails, the Central Repository will be disabled and the current - * settings will be cleared. - */ - @Messages({"EamDbUtil.centralRepoDisabled.message= The Central Repository has been disabled.", - "EamDbUtil.centralRepoUpgradeFailed.message=Failed to upgrade Central Repository.", - "EamDbUtil.centralRepoConnectionFailed.message=Unable to connect to Central Repository.", - "EamDbUtil.exclusiveLockAquisitionFailure.message=Unable to acquire exclusive lock for Central Repository."}) - public static void upgradeDatabase() throws CentralRepoException { - if (!CentralRepository.isEnabled()) { - EamDbSettingsDialog dialog = new EamDbSettingsDialog(); - dialog. - promptUserForSetup(); - } - - CentralRepository db = null; - CoordinationService.Lock lock = null; - - //get connection - try { - try { - db = CentralRepository.getInstance(); - } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); - throw new CentralRepoException("Error updating central repository, unable to make connection", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } - //get lock necessary for upgrade - if (db != null) { - try { - // This may return null if locking isn't supported, which is fine. It will - // throw an exception if locking is supported but we can't get the lock - // (meaning the database is in use by another user) - lock = db.getExclusiveMultiUserDbLock(); - //perform upgrade - } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); - throw new CentralRepoException("Error updating central repository, unable to acquire exclusive lock", Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } - - try { - db.upgradeSchema(); - } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "Error updating central repository", ex); - throw new CentralRepoException("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error updating central repository", ex); - throw new CentralRepoException("Error updating central repository", Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } catch (IncompatibleCentralRepoException ex) { - LOGGER.log(Level.SEVERE, "Error updating central repository", ex); - throw new CentralRepoException("Error updating central repository", ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } finally { - if (lock != null) { - try { - lock.release(); - } catch (CoordinationServiceException ex) { - LOGGER.log(Level.SEVERE, "Error releasing database lock", ex); - } - } - } - } else { - throw new CentralRepoException("Unable to connect to database", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message()); - } - } catch (CentralRepoException ex) { - // Disable the central repo and clear the current settings. - try { - if (null != CentralRepository.getInstance()) { - CentralRepository.getInstance().shutdownConnections(); - } - } catch (CentralRepoException ex2) { - LOGGER.log(Level.SEVERE, "Error shutting down central repo connection pool", ex2); - } - CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.DISABLED.name()); - CentralRepoPlatforms.saveSelectedPlatform(); - throw ex; - } - } /** * Get the default organization name diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java similarity index 75% rename from Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java rename to Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java index f936e6af55..d7a13b6041 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/DatabaseTestResult.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java @@ -3,9 +3,9 @@ * To change this template file, choose Tools | Templates * and open the template in the editor. */ -package org.sleuthkit.autopsy.centralrepository.optionspanel; +package org.sleuthkit.autopsy.centralrepository.datamodel; -enum DatabaseTestResult { +public enum DatabaseTestResult { UNTESTED, CONNECTION_FAILED, SCHEMA_INVALID, diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 272a9047bb..73ab88d87c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -23,6 +23,7 @@ import org.openide.modules.ModuleInstall; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil; import org.sleuthkit.autopsy.core.RuntimeProperties; @@ -59,7 +60,7 @@ public class Installer extends ModuleInstall { // Perform the database upgrade and inform the user if it fails try { - CentralRepoDbUtil.upgradeDatabase(); + CentralRepoDbManager.upgradeDatabase(); } catch (CentralRepoException ex) { if (RuntimeProperties.runningWithGUI()) { WindowManager.getDefault().invokeWhenUIReady(() -> { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 4bd17b561e..c6518d4b2e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -35,8 +35,10 @@ import javax.swing.event.DocumentEvent; import javax.swing.event.DocumentListener; import javax.swing.filechooser.FileFilter; import org.netbeans.spi.options.OptionsPanelController; +import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.openide.windows.WindowManager; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager; import org.sleuthkit.autopsy.corecomponents.TextPrompt; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; @@ -45,7 +47,7 @@ import static org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatf import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings; import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; -import org.sleuthkit.autopsy.centralrepository.optionspanel.DatabaseTestResult; +import org.sleuthkit.autopsy.centralrepository.datamodel.DatabaseTestResult; /** * Configuration dialog for Central Repository database settings. @@ -58,10 +60,45 @@ public class EamDbSettingsDialog extends JDialog { private static final long serialVersionUID = 1L; private final Collection textBoxes; private final TextBoxChangedListener textBoxChangedListener; + private final CentralRepoDbManager manager = new CentralRepoDbManager(); + /** + * prompts user based on testing status (i.e. failure to connect, invalid schema, db does not exist, etc.) + * @return whether or not the ultimate status after prompts is okay to continue + */ + @NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", + "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", + "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", + "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?", + "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed", + "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again."}) + private boolean promptTestStatusWarnings() { + if (manager.getStatus() == DatabaseTestResult.CONNECTION_FAILED) { + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(), + Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(), + JOptionPane.WARNING_MESSAGE); + } else if (manager.getStatus() == DatabaseTestResult.SCHEMA_INVALID) { + // There's an existing database or file, but it's not in our format. + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(), + Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(), + JOptionPane.WARNING_MESSAGE); + } else if (manager.getStatus() == DatabaseTestResult.DB_DOES_NOT_EXIST) { + //database doesn't exist do you want to create + boolean createDb = (!warnDoesNotExist || + JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(), + Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(), + JOptionPane.YES_NO_OPTION)); + + if (createDb) + manager.createDb(); + } - + return (manager.getStatus() == DatabaseTestResult.TESTEDOK); + } /** @@ -98,7 +135,7 @@ public class EamDbSettingsDialog extends JDialog { return "Directories and Central Repository databases"; } }); - cbDatabaseType.setSelectedItem(selectedPlatform); + cbDatabaseType.setSelectedItem(manager.getSelectedPlatform()); customizeComponents(); valid(); display(); @@ -351,7 +388,7 @@ public class EamDbSettingsDialog extends JDialog { private void customizeComponents() { setTextPrompts(); setTextBoxListeners(); - switch (selectedPlatform) { + switch (manager.getSelectedPlatform()) { case SQLITE: testingStatus = DatabaseTestResult.UNTESTED; updatePostgresFields(false); @@ -396,15 +433,15 @@ public class EamDbSettingsDialog extends JDialog { private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); - testDbSettings(); + manager.testStatus(); - boolean testedOk = promptTestStatusWarnings(true); + boolean testedOk = promptTestStatusWarnings(); if (!testedOk) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); return; } - saveNewCentralRepo(); + manager.saveNewCentralRepo(); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); dispose(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java index ebd85ba527..ab0ea0401f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/GlobalSettingsPanel.java @@ -31,6 +31,7 @@ import org.netbeans.spi.options.OptionsPanelController; import org.openide.util.NbBundle; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.corecomponents.OptionsPanel; import org.sleuthkit.autopsy.events.AutopsyEvent; @@ -86,7 +87,7 @@ public final class GlobalSettingsPanel extends IngestModuleGlobalSettingsPanel i setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); try { - CentralRepoDbUtil.upgradeDatabase(); + CentralRepoDbManager.upgradeDatabase(); setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); } catch (CentralRepoException ex) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); From 5419db1deae1c55c910be02ababd9082ac86c441 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Fri, 14 Feb 2020 12:32:09 -0500 Subject: [PATCH 11/77] working through refactoring of classes --- .../datamodel/CentralRepoDbManager.java | 187 +++++++-------- .../optionspanel/EamDbSettingsDialog.java | 220 +++++++++--------- .../netbeans/core/startup/Bundle.properties | 4 +- .../core/windows/view/ui/Bundle.properties | 6 +- 4 files changed, 188 insertions(+), 229 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 9a50b7f209..5df9b445b9 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -24,6 +24,10 @@ public class CentralRepoDbManager { private static final Logger logger = Logger.getLogger(CentralRepoDbManager.class.getName()); + public static String getDefaultSqliteDbName() { + return CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT; + } + /** * Upgrade the current Central Reposity schema to the newest version. If the * upgrade fails, the Central Repository will be disabled and the current @@ -32,8 +36,9 @@ public class CentralRepoDbManager { @NbBundle.Messages(value = {"EamDbUtil.centralRepoDisabled.message= The Central Repository has been disabled.", "EamDbUtil.centralRepoUpgradeFailed.message=Failed to upgrade Central Repository.", "EamDbUtil.centralRepoConnectionFailed.message=Unable to connect to Central Repository.", "EamDbUtil.exclusiveLockAquisitionFailure.message=Unable to acquire exclusive lock for Central Repository."}) public static void upgradeDatabase() throws CentralRepoException { if (!CentralRepository.isEnabled()) { - EamDbSettingsDialog dialog = new EamDbSettingsDialog(); - dialog.promptUserForSetup(); + // TODO +// EamDbSettingsDialog dialog = new EamDbSettingsDialog(); +// dialog.promptUserForSetup(); } CentralRepository db = null; CoordinationService.Lock lock = null; @@ -42,7 +47,7 @@ public class CentralRepoDbManager { try { db = CentralRepository.getInstance(); } catch (CentralRepoException ex) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); + logger.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); throw new CentralRepoException("Error updating central repository, unable to make connection", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); } //get lock necessary for upgrade @@ -54,26 +59,26 @@ public class CentralRepoDbManager { lock = db.getExclusiveMultiUserDbLock(); //perform upgrade } catch (CentralRepoException ex) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); + logger.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); throw new CentralRepoException("Error updating central repository, unable to acquire exclusive lock", Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); } try { db.upgradeSchema(); } catch (CentralRepoException ex) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository", ex); + logger.log(Level.SEVERE, "Error updating central repository", ex); throw new CentralRepoException("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); } catch (SQLException ex) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository", ex); + logger.log(Level.SEVERE, "Error updating central repository", ex); throw new CentralRepoException("Error updating central repository", Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); } catch (IncompatibleCentralRepoException ex) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error updating central repository", ex); + logger.log(Level.SEVERE, "Error updating central repository", ex); throw new CentralRepoException("Error updating central repository", ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); } finally { if (lock != null) { try { lock.release(); } catch (CoordinationService.CoordinationServiceException ex) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error releasing database lock", ex); + logger.log(Level.SEVERE, "Error releasing database lock", ex); } } } @@ -87,7 +92,7 @@ public class CentralRepoDbManager { CentralRepository.getInstance().shutdownConnections(); } } catch (CentralRepoException ex2) { - CentralRepoDbUtil.LOGGER.log(Level.SEVERE, "Error shutting down central repo connection pool", ex2); + logger.log(Level.SEVERE, "Error shutting down central repo connection pool", ex2); } CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.DISABLED.name()); CentralRepoPlatforms.saveSelectedPlatform(); @@ -115,62 +120,76 @@ public class CentralRepoDbManager { selectedPlatform = CentralRepoPlatforms.POSTGRESQL; } } - + public PostgresCentralRepoSettings getDbSettingsPostgres() { + return dbSettingsPostgres; + } + public SqliteCentralRepoSettings getDbSettingsSqlite() { + return dbSettingsSqlite; + } - - - - - @NbBundle.Messages({"EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database", - "EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.", - "EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again."}) - public boolean createDb() { - boolean result = false; + public boolean createDb() throws CentralRepoException { boolean dbCreated = true; switch (selectedPlatform) { case POSTGRESQL: + // if postgres database does not exist, attempt to create it if (!dbSettingsPostgres.verifyDatabaseExists()) { dbCreated = dbSettingsPostgres.createDatabase(); } - if (dbCreated) { - result = dbSettingsPostgres.initializeDatabaseSchema() - && dbSettingsPostgres.insertDefaultDatabaseContent(); + + // if the database still isn't created, we have a problem + if (!dbCreated) { + logger.severe("Unable to create Postgres database for Central Repository at " + + dbSettingsPostgres.getHost() + ":" + dbSettingsPostgres.getPort() + " with db name: " + + dbSettingsPostgres.getDbName() + " and username: " + dbSettingsPostgres.getUserName()); + + throw new CentralRepoException("Unable to create Postgres database for Central Repository."); } + + + boolean result = dbSettingsPostgres.initializeDatabaseSchema() + && dbSettingsPostgres.insertDefaultDatabaseContent(); + + // if unable to initialize the schema, there's a problem as well if (!result) { // Remove the incomplete database if (dbCreated) { dbSettingsPostgres.deleteDatabase(); } - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createPostgresDbError_message(), - Bundle.EamDbSettingsDialog_okButton_createDbError_title(), - JOptionPane.WARNING_MESSAGE); - logger.severe("Unable to initialize database schema or insert contents into central repository."); - return false; + String schemaError = "Unable to initialize database schema or insert contents into central repository."; + logger.severe(schemaError); + throw new CentralRepoException(schemaError); } + break; case SQLITE: + + // if sqlite db does not exist, try to creat it if (!dbSettingsSqlite.dbDirectoryExists()) { dbCreated = dbSettingsSqlite.createDbDirectory(); } - if (dbCreated) { - result = dbSettingsSqlite.initializeDatabaseSchema() - && dbSettingsSqlite.insertDefaultDatabaseContent(); + + // if the database still isn't created, we have a problem + if (!dbCreated) { + logger.severe("Unable to create Sqlite database for Central Repository at " + + dbSettingsSqlite.getDbDirectory()); + + throw new CentralRepoException("Unable to create SQLite database for Central Repository."); } + + result = dbSettingsSqlite.initializeDatabaseSchema() + && dbSettingsSqlite.insertDefaultDatabaseContent(); + if (!result) { if (dbCreated) { dbSettingsSqlite.deleteDatabase(); } - - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createSQLiteDbError_message(), - Bundle.EamDbSettingsDialog_okButton_createDbError_title(), - JOptionPane.WARNING_MESSAGE); - logger.severe("Unable to initialize database schema or insert contents into central repository."); - return false; + + String schemaError = "Unable to initialize database schema or insert contents into central repository."; + logger.severe(schemaError); + throw new CentralRepoException(schemaError); } break; } @@ -182,10 +201,8 @@ public class CentralRepoDbManager { /** * saves a new central repository based on current settings */ - @NbBundle.Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.", - "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.", - "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database."}) - private void saveNewCentralRepo() { + @NbBundle.Messages({"CentralRepoDbManager.connectionErrorMsg.text=Failed to connect to central repository database."}) + public void saveNewCentralRepo() throws CentralRepoException { /** * We have to shutdown the previous platform's connection pool first; * assuming it wasn't DISABLED. This will close any existing idle @@ -202,12 +219,7 @@ public class CentralRepoDbManager { } } catch (CentralRepoException ex) { logger.log(Level.SEVERE, "Failed to close database connections in previously selected platform.", ex); // NON-NLS - SwingUtilities.invokeLater(() -> { - JOptionPane.showMessageDialog(this, - Bundle.EamDbSettingsDialog_okButton_errorMsg_text(), - Bundle.EamDbSettingsDialog_okButton_errorTitle_text(), - JOptionPane.WARNING_MESSAGE); - }); + throw ex; } // Even if we fail to close the existing connections, make sure that we @@ -226,8 +238,7 @@ public class CentralRepoDbManager { CentralRepository.getInstance().updateSettings(); configurationChanged = true; } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex); //NON-NLS - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + logger.log(Level.SEVERE, Bundle.CentralRepoDbManager_connectionErrorMsg_text(), ex); //NON-NLS return; } @@ -241,8 +252,7 @@ public class CentralRepoDbManager { CentralRepository.getInstance().updateSettings(); configurationChanged = true; } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, Bundle.EamDbSettingsDialog_okButton_connectionErrorMsg_text(), ex); //NON-NLS - setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); + logger.log(Level.SEVERE, Bundle.CentralRepoDbManager_connectionErrorMsg_text(), ex); //NON-NLS return; } break; @@ -252,30 +262,22 @@ public class CentralRepoDbManager { } public DatabaseTestResult getStatus() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + return testingStatus; } public CentralRepoPlatforms getSelectedPlatform() { return selectedPlatform; } - - - static class DatabaseSettingsValidResult { - private final String errorMessage; - private final boolean success; - public DatabaseSettingsValidResult(String errorMessage, boolean success) { - this.errorMessage = errorMessage; - this.success = success; - } + public void clearStatus() { + testingStatus = DatabaseTestResult.UNTESTED; + } - public String getErrorMessage() { - return errorMessage; - } - public boolean isSuccess() { - return success; - } + + public void setSelectedPlatform(CentralRepoPlatforms newSelected) { + selectedPlatform = newSelected; + testingStatus = DatabaseTestResult.UNTESTED; } @@ -284,66 +286,33 @@ public class CentralRepoDbManager { * * @return True or false. */ - private DatabaseSettingsValidResult databaseSettingsAreValid( - String tbDbHostname, Integer tbDbPort, String tbDbUsername, String tfDatabasePath, String jpDbPassword) { + public boolean testDatabaseSettingsAreValid ( + String tbDbHostname, String tbDbPort, String tbDbUsername, String tfDatabasePath, String jpDbPassword) throws CentralRepoException, NumberFormatException { boolean result = true; StringBuilder guidanceText = new StringBuilder(); switch (selectedPlatform) { case POSTGRESQL: - try { dbSettingsPostgres.setHost(tbDbHostname); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { - dbSettingsPostgres.setPort(tbDbPort); - } catch (NumberFormatException | CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { + dbSettingsPostgres.setPort(Integer.parseInt(tbDbPort)); dbSettingsPostgres.setDbName(CENTRAL_REPO_DB_NAME); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { dbSettingsPostgres.setUserName(tbDbUsername); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { dbSettingsPostgres.setPassword(jpDbPassword); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } break; case SQLITE: - try { File databasePath = new File(tfDatabasePath); - dbSettingsSqlite.setDbName(CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT); + dbSettingsSqlite.setDbName(getDefaultSqliteDbName()); dbSettingsSqlite.setDbDirectory(databasePath.getPath()); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } break; + default: + throw new IllegalStateException("Central Repo has an unknown selected platform: " + selectedPlatform); } - return new DatabaseSettingsValidResult(guidanceText.toString(), result); + return result; } - - private DatabaseTestResult testDbSettings() { + public DatabaseTestResult testStatus() { switch (selectedPlatform) { case POSTGRESQL: if (dbSettingsPostgres.verifyConnection()) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index c6518d4b2e..51659aa21f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -43,10 +43,6 @@ import org.sleuthkit.autopsy.corecomponents.TextPrompt; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatforms; -import static org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatforms.SQLITE; -import org.sleuthkit.autopsy.centralrepository.datamodel.PostgresCentralRepoSettings; -import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.centralrepository.datamodel.DatabaseTestResult; /** @@ -63,44 +59,6 @@ public class EamDbSettingsDialog extends JDialog { private final CentralRepoDbManager manager = new CentralRepoDbManager(); - /** - * prompts user based on testing status (i.e. failure to connect, invalid schema, db does not exist, etc.) - * @return whether or not the ultimate status after prompts is okay to continue - */ - @NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", - "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", - "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", - "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?", - "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed", - "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again."}) - private boolean promptTestStatusWarnings() { - if (manager.getStatus() == DatabaseTestResult.CONNECTION_FAILED) { - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(), - Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(), - JOptionPane.WARNING_MESSAGE); - } else if (manager.getStatus() == DatabaseTestResult.SCHEMA_INVALID) { - // There's an existing database or file, but it's not in our format. - JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(), - Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(), - JOptionPane.WARNING_MESSAGE); - } else if (manager.getStatus() == DatabaseTestResult.DB_DOES_NOT_EXIST) { - //database doesn't exist do you want to create - boolean createDb = (!warnDoesNotExist || - JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), - Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(), - Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(), - JOptionPane.YES_NO_OPTION)); - - if (createDb) - manager.createDb(); - } - - return (manager.getStatus() == DatabaseTestResult.TESTEDOK); - } - - /** * Creates new form EamDbSettingsDialog */ @@ -108,7 +66,6 @@ public class EamDbSettingsDialog extends JDialog { "EamDbSettingsDialog.lbSingleUserSqLite.text=SQLite should only be used by one examiner at a time.", "EamDbSettingsDialog.lbDatabaseType.text=Database Type :", "EamDbSettingsDialog.fcDatabasePath.title=Select location for central_repository.db"}) - public EamDbSettingsDialog() { super((JFrame) WindowManager.getDefault().getMainWindow(), Bundle.EamDbSettingsDialog_title_text(), @@ -127,7 +84,7 @@ public class EamDbSettingsDialog extends JDialog { if (pathname.isDirectory()) { return true; } - return pathname.getName().toLowerCase().equals((CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT).toLowerCase()); + return pathname.getName().equalsIgnoreCase(CentralRepoDbManager.getDefaultSqliteDbName()); } @Override @@ -141,6 +98,69 @@ public class EamDbSettingsDialog extends JDialog { display(); } + + + + /** + * prompts user based on testing status (i.e. failure to connect, invalid schema, db does not exist, etc.) + * @return whether or not the ultimate status after prompts is okay to continue + */ + @NbBundle.Messages({"EamDbSettingsDialog.okButton.corruptDatabaseExists.title=Error Loading Database", + "EamDbSettingsDialog.okButton.corruptDatabaseExists.message=Database exists but is not the right format. Manually delete it or choose a different path (if applicable).", + "EamDbSettingsDialog.okButton.createDbDialog.title=Database Does Not Exist", + "EamDbSettingsDialog.okButton.createDbDialog.message=Database does not exist, would you like to create it?", + "EamDbSettingsDialog.okButton.databaseConnectionFailed.title=Database Connection Failed", + "EamDbSettingsDialog.okButton.databaseConnectionFailed.message=Unable to connect to database please check your settings and try again.", + "EamDbSettingsDialog.okButton.createSQLiteDbError.message=Unable to create SQLite Database, please ensure location exists and you have write permissions and try again.", + "EamDbSettingsDialog.okButton.createPostgresDbError.message=Unable to create Postgres Database, please ensure address, port, and login credentials are correct for Postgres server and try again.", + "EamDbSettingsDialog.okButton.createDbError.title=Unable to Create Database"}) + private boolean promptTestStatusWarnings() { + if (manager.getStatus() == DatabaseTestResult.CONNECTION_FAILED) { + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_message(), + Bundle.EamDbSettingsDialog_okButton_databaseConnectionFailed_title(), + JOptionPane.WARNING_MESSAGE); + } else if (manager.getStatus() == DatabaseTestResult.SCHEMA_INVALID) { + // There's an existing database or file, but it's not in our format. + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_message(), + Bundle.EamDbSettingsDialog_okButton_corruptDatabaseExists_title(), + JOptionPane.WARNING_MESSAGE); + } else if (manager.getStatus() == DatabaseTestResult.DB_DOES_NOT_EXIST) { + //database doesn't exist. do you want to create? + if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), + Bundle.EamDbSettingsDialog_okButton_createDbDialog_message(), + Bundle.EamDbSettingsDialog_okButton_createDbDialog_title(), + JOptionPane.YES_NO_OPTION)) { + try { + manager.createDb(); + } + catch (CentralRepoException e) { + // in the event that there is a failure to connect, notify user with corresponding message + String errorMessage; + switch (manager.getSelectedPlatform()) { + case POSTGRESQL: + errorMessage = Bundle.EamDbSettingsDialog_okButton_createPostgresDbError_message(); + break; + case SQLITE: + errorMessage = Bundle.EamDbSettingsDialog_okButton_createSQLiteDbError_message(); + break; + default: + errorMessage = ""; + break; + } + + JOptionPane.showMessageDialog(WindowManager.getDefault().getMainWindow(), + errorMessage, + Bundle.EamDbSettingsDialog_okButton_createDbError_title(), + JOptionPane.WARNING_MESSAGE); + } + } + } + + return (manager.getStatus() == DatabaseTestResult.TESTEDOK); + } + /** * This method is called from within the constructor to initialize the form. @@ -388,21 +408,20 @@ public class EamDbSettingsDialog extends JDialog { private void customizeComponents() { setTextPrompts(); setTextBoxListeners(); + manager.clearStatus(); switch (manager.getSelectedPlatform()) { case SQLITE: - testingStatus = DatabaseTestResult.UNTESTED; updatePostgresFields(false); updateSqliteFields(true); break; default: POSTGRESQL: - testingStatus = DatabaseTestResult.UNTESTED; updatePostgresFields(true); updateSqliteFields(false); break; } - displayDatabaseSettings(selectedPlatform.equals(CentralRepoPlatforms.POSTGRESQL)); + displayDatabaseSettings(CentralRepoPlatforms.POSTGRESQL.equals(manager.getSelectedPlatform())); } private void display() { @@ -412,7 +431,7 @@ public class EamDbSettingsDialog extends JDialog { @Messages({"EamDbSettingsDialog.chooserPath.failedToGetDbPathMsg=Selected database path is invalid. Try again."}) private void bnDatabasePathFileOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnDatabasePathFileOpenActionPerformed - fcDatabasePath.setSelectedFile(new File(dbSettingsSqlite.getDbDirectory())); + fcDatabasePath.setSelectedFile(new File(manager.getDbSettingsSqlite().getDbDirectory())); if (fcDatabasePath.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) { File databaseFile = fcDatabasePath.getSelectedFile(); if (databaseFile.isFile()) { @@ -428,9 +447,9 @@ public class EamDbSettingsDialog extends JDialog { } }//GEN-LAST:event_bnDatabasePathFileOpenActionPerformed - - - + @NbBundle.Messages({"EamDbSettingsDialog.okButton.errorTitle.text=Restart Required.", + "EamDbSettingsDialog.okButton.errorMsg.text=Please restart Autopsy to begin using the new database platform.", + "EamDbSettingsDialog.okButton.connectionErrorMsg.text=Failed to connect to central repository database."}) private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); manager.testStatus(); @@ -441,7 +460,18 @@ public class EamDbSettingsDialog extends JDialog { return; } - manager.saveNewCentralRepo(); + try{ + manager.saveNewCentralRepo(); + } + catch (CentralRepoException e) { + SwingUtilities.invokeLater(() -> { + JOptionPane.showMessageDialog(this, + Bundle.EamDbSettingsDialog_okButton_errorMsg_text(), + EamDbSettingsDialog_okButton_errorTitle_text(), + JOptionPane.WARNING_MESSAGE); + }); + } + setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); dispose(); @@ -455,12 +485,12 @@ public class EamDbSettingsDialog extends JDialog { private void cbDatabaseTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cbDatabaseTypeActionPerformed - selectedPlatform = (CentralRepoPlatforms) cbDatabaseType.getSelectedItem(); + manager.setSelectedPlatform((CentralRepoPlatforms) cbDatabaseType.getSelectedItem()); customizeComponents(); }//GEN-LAST:event_cbDatabaseTypeActionPerformed private void updateFullDbPath() { - dataBaseFileTextArea.setText(tfDatabasePath.getText() + File.separator + CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT); + dataBaseFileTextArea.setText(tfDatabasePath.getText() + File.separator + manager.getDefaultSqliteDbName()); dataBaseFileTextArea.setCaretPosition(dataBaseFileTextArea.getText().length()); } @@ -498,13 +528,13 @@ public class EamDbSettingsDialog extends JDialog { } private void updatePostgresFields(boolean enabled) { - tbDbHostname.setText(enabled ? dbSettingsPostgres.getHost() : ""); + tbDbHostname.setText(enabled ? manager.getDbSettingsPostgres().getHost() : ""); tbDbHostname.setEnabled(enabled); - tbDbPort.setText(enabled ? Integer.toString(dbSettingsPostgres.getPort()) : ""); + tbDbPort.setText(enabled ? Integer.toString(manager.getDbSettingsPostgres().getPort()) : ""); tbDbPort.setEnabled(enabled); - tbDbUsername.setText(enabled ? dbSettingsPostgres.getUserName() : ""); + tbDbUsername.setText(enabled ? manager.getDbSettingsPostgres().getUserName() : ""); tbDbUsername.setEnabled(enabled); - jpDbPassword.setText(enabled ? dbSettingsPostgres.getPassword() : ""); + jpDbPassword.setText(enabled ? manager.getDbSettingsPostgres().getPassword() : ""); jpDbPassword.setEnabled(enabled); } @@ -515,7 +545,7 @@ public class EamDbSettingsDialog extends JDialog { * @param enabled */ private void updateSqliteFields(boolean enabled) { - tfDatabasePath.setText(enabled ? dbSettingsSqlite.getDbDirectory() : ""); + tfDatabasePath.setText(enabled ? manager.getDbSettingsSqlite().getDbDirectory() : ""); tfDatabasePath.setEnabled(enabled); bnDatabasePathFileOpen.setEnabled(enabled); } @@ -568,7 +598,7 @@ public class EamDbSettingsDialog extends JDialog { @Messages({"EamDbSettingsDialog.validation.incompleteFields=Fill in all values for the selected database."}) private boolean databaseFieldsArePopulated() { boolean result = true; - switch (selectedPlatform) { + switch (manager.getSelectedPlatform()) { case POSTGRESQL: result = !tbDbHostname.getText().trim().isEmpty() && !tbDbPort.getText().trim().isEmpty() @@ -634,59 +664,19 @@ public class EamDbSettingsDialog extends JDialog { * @return True or false. */ private boolean databaseSettingsAreValid() { - boolean result = true; - StringBuilder guidanceText = new StringBuilder(); - - switch (selectedPlatform) { - case POSTGRESQL: - try { - dbSettingsPostgres.setHost(tbDbHostname.getText().trim()); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { - dbSettingsPostgres.setPort(Integer.valueOf(tbDbPort.getText().trim())); - } catch (NumberFormatException | CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { - dbSettingsPostgres.setDbName(CENTRAL_REPO_DB_NAME); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { - dbSettingsPostgres.setUserName(tbDbUsername.getText().trim()); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - - try { - dbSettingsPostgres.setPassword(new String(jpDbPassword.getPassword())); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - break; - case SQLITE: - try { - File databasePath = new File(tfDatabasePath.getText()); - dbSettingsSqlite.setDbName(CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT); - dbSettingsSqlite.setDbDirectory(databasePath.getPath()); - } catch (CentralRepoException ex) { - guidanceText.append(ex.getMessage()); - result = false; - } - break; + try { + manager.testDatabaseSettingsAreValid( + tbDbHostname.getText().trim(), + tbDbPort.getText().trim(), + tbDbUsername.getText().trim(), + tfDatabasePath.getText().trim(), + new String(jpDbPassword.getPassword())); } - - return result; + catch (Exception e) { + return false; + } + + return true; } /** @@ -698,7 +688,7 @@ public class EamDbSettingsDialog extends JDialog { @Override public void changedUpdate(DocumentEvent e) { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - testingStatus = DatabaseTestResult.UNTESTED; + manager.clearStatus(); updateFullDbPath(); valid(); } @@ -706,7 +696,7 @@ public class EamDbSettingsDialog extends JDialog { @Override public void insertUpdate(DocumentEvent e) { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - testingStatus = DatabaseTestResult.UNTESTED; + manager.clearStatus(); updateFullDbPath(); valid(); } @@ -714,7 +704,7 @@ public class EamDbSettingsDialog extends JDialog { @Override public void removeUpdate(DocumentEvent e) { firePropertyChange(OptionsPanelController.PROP_CHANGED, null, null); - testingStatus = DatabaseTestResult.UNTESTED; + manager.clearStatus(); updateFullDbPath(); valid(); 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 b20ccf5912..4f645919d3 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 -#Tue, 12 Nov 2019 17:21:46 -0500 +#Fri, 14 Feb 2020 12:16:52 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.13.0 +currentVersion=Autopsy 4.14.0 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 998d3f715c..627464541f 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,4 +1,4 @@ #Updated by build script -#Tue, 12 Nov 2019 17:21:46 -0500 -CTL_MainWindow_Title=Autopsy 4.13.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 +#Fri, 14 Feb 2020 12:16:52 -0500 +CTL_MainWindow_Title=Autopsy 4.14.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.14.0 From 57a6fdac6975c42add7ede8973d027b32887dac1 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 18 Feb 2020 09:41:35 -0500 Subject: [PATCH 12/77] Updated to based on jira and review comments --- .../autopsy/geolocation/datamodel/Route.java | 11 ++-- .../autopsy/geolocation/datamodel/Track.java | 62 ++++--------------- .../modules/drones/Bundle.properties-MERGED | 4 +- .../autopsy/modules/drones/DATExtractor.java | 14 +++-- .../android/googlemaplocation.py | 9 ++- 5 files changed, 37 insertions(+), 63 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index 31372ea4fe..fa8dacf5d2 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -20,13 +20,14 @@ package org.sleuthkit.autopsy.geolocation.datamodel; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.GeoWaypoints; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints.GeoWaypoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints; /** * A Route represents a TSK_GPS_ROUTE artifact which has a start and end point @@ -117,9 +118,11 @@ public class Route extends GeoPath { if (attribute != null) { String value = attribute.getValueString(); - List waypointList = GeoWaypoints.deserializePoints(value); + GeoWaypoints waypoints = GeoWaypoints.deserialize(value); - for (GeoWaypoint waypoint : waypointList) { + Iterator waypointIter = waypoints.iterator(); + while(waypointIter.hasNext()) { + GeoWaypoint waypoint = waypointIter.next(); addToPath(new Waypoint(artifact, label, null, waypoint.getLatitude(), waypoint.getLongitude(), waypoint.getAltitude(), null, attributeMap, this)); } } else { diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java index cb0dd95303..33294d0d18 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java @@ -21,13 +21,14 @@ package org.sleuthkit.autopsy.geolocation.datamodel; import java.util.ArrayList; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.GeoTrackPoint; /** * A GPS track with which wraps the TSK_GPS_TRACK artifact. @@ -59,11 +60,11 @@ public final class Track extends GeoPath{ private Track(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException { super(artifact, getTrackName(attributeMap)); - List points = getPointsList(attributeMap); + GeoTrackPoints points = getPointsList(attributeMap); buildPath(points); - startTimestamp = findStartTime(points); - endTimeStamp = findEndTime(points); + startTimestamp = points.getStartTime(); + endTimeStamp = points.getEndTime(); } /** @@ -111,8 +112,10 @@ public final class Track extends GeoPath{ "# {0} - track name", "GEOTrack_point_label_header=Trackpoint for track: {0}" }) - private void buildPath(List points) throws GeoLocationDataException { - for (GeoTrackPoint point : points) { + private void buildPath(GeoTrackPoints points) throws GeoLocationDataException { + Iterator pointIter = points.iterator(); + while(pointIter.hasNext()) { + GeoTrackPoint point = pointIter.next(); addToPath(new TrackWaypoint(Bundle.GEOTrack_point_label_header(getLabel()), point)); } } @@ -125,52 +128,13 @@ public final class Track extends GeoPath{ * * @return GeoTrackPoint list empty list if the attribute was not found. */ - private List getPointsList(Map attributeMap) { + private GeoTrackPoints getPointsList(Map attributeMap) { BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS); if (attribute != null) { String value = attribute.getValueString(); - return GeoTrackPoints.deserializePoints(value); + return GeoTrackPoints.deserialize(value); } - return new ArrayList<>(); - } - - /** - * Return the start time for the track. Assumes the points are in time - * order. - * - * @param points List of GeoTrackPoints. - * - * @return First non-null time stamp or null, if one was not found. - */ - private Long findStartTime(List points) { - if (points != null) { - for (GeoTrackPoint point : points) { - if (point.getTimeStamp() != null) { - return point.getTimeStamp(); - } - } - } - return null; - } - - /** - * Return the ends time for the track. Assumes the points are in time - * order. - * - * @param points List of GeoTrackPoints. - * - * @return First non-null time stamp or null, if one was not found. - */ - private Long findEndTime(List points) { - if (points != null) { - for (int index = points.size() - 1; index >= 0; index--) { - GeoTrackPoint point = points.get(index); - if (point.getTimeStamp() != null) { - return point.getTimeStamp(); - } - } - } return null; } @@ -234,12 +198,12 @@ public final class Track extends GeoPath{ value = point.getDistanceTraveled(); if (value != null) { - list.add(new Property(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_DISTANCE_TRAVELED.getDisplayName(), value.toString())); + list.add(new Property("", value.toString())); } value = point.getDistanceFromHP(); if (value != null) { - list.add(new Property(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_DISTANCE_FROM_HOME_POINT.getDisplayName(), value.toString())); + list.add(new Property("", value.toString())); } return list; diff --git a/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED index 23f2a02775..bf61ad9be0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED @@ -1,6 +1,6 @@ DATExtractor_process_message=Processing DJI DAT file: %s DATFileExtractor_Extractor_Name=DAT File Extractor -DroneIngestModule_Description=Description -DroneIngestModule_Name=Drone +DroneIngestModule_Description=Analyzes files generated by drones. +DroneIngestModule_Name=Drone Analyzer # {0} - AbstractFileName DroneIngestModule_process_start=Started {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java index 256ee59509..68947be6fa 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java @@ -41,10 +41,11 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoint.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPointList.GeoTrackPoint; import org.sleuthkit.datamodel.blackboardutils.GeoArtifactsHelper; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.Blackboard.BlackboardException; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPointList; /** * Extract drone position data from DJI Phantom drones. @@ -110,10 +111,10 @@ final class DATExtractor extends DroneExtractor { } // Process the csv file - List trackPoints = processCSVFile(context, DATFile, csvFilePath); + GeoTrackPointList trackPoints = processCSVFile(context, DATFile, csvFilePath); if (trackPoints != null && !trackPoints.isEmpty()) { - (new GeoArtifactsHelper(getSleuthkitCase(), getName(), DATFile)).addTrack(DATFile.getName(), trackPoints); + (new GeoArtifactsHelper(getSleuthkitCase(), getName(), "DatCon", DATFile)).addTrack(DATFile.getName(), trackPoints, null); } else { logger.log(Level.INFO, String.format("No trackpoints with valid longitude or latitude found in %s", DATFile.getName())); //NON-NLS } @@ -187,8 +188,8 @@ final class DATExtractor extends DroneExtractor { * * @throws DroneIngestException */ - private List processCSVFile(IngestJobContext context, AbstractFile DATFile, String csvFilePath) throws DroneIngestException { - List trackPoints = new ArrayList<>(); + private GeoTrackPointList processCSVFile(IngestJobContext context, AbstractFile DATFile, String csvFilePath) throws DroneIngestException { + GeoTrackPointList trackPoints = new GeoTrackPointList(); try (BufferedReader reader = new BufferedReader(new FileReader(new File(csvFilePath)))) { // First read in the header line and process String line = reader.readLine(); @@ -202,7 +203,7 @@ final class DATExtractor extends DroneExtractor { String[] values = line.split(","); //NON-NLS GeoTrackPoint point = createTrackPoint(headerMap, values); if (point != null) { - trackPoints.add(point); + trackPoints.addPoint(point); } } @@ -258,6 +259,7 @@ final class DATExtractor extends DroneExtractor { return new GeoTrackPoint(latitude, longitude, getDoubleValue(columnLookup.get(HEADER_ALTITUDE), values), + null, getDoubleValue(columnLookup.get(HEADER_VELOCITY), values), getDoubleValue(columnLookup.get(HEADER_DISTANCE_FROM_HP), values), getDoubleValue(columnLookup.get(HEADER_DISTANCE_TRAVELED), values), diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index 17522c576c..330095c900 100644 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -42,6 +42,7 @@ from org.sleuthkit.datamodel import BlackboardAttribute from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypointList import traceback import general @@ -87,7 +88,7 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): try: artifactHelper = GeoArtifactsHelper(self.current_case.getSleuthkitCase(), - general.MODULE_NAME, abstractFile) + general.MODULE_NAME, self.PROGRAM_NAME, abstractFile) Class.forName("org.sqlite.JDBC") # load JDBC driver connection = DriverManager.getConnection("jdbc:sqlite:" + databasePath) statement = connection.createStatement() @@ -113,8 +114,12 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): dest_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("dest_lng")) source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat")) source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng")) + + waypointlist = GeoWaypointList() + waypointlist.addPoint(source_lat, source_lng, None, None) + waypointlist.addPoint(dest_lat, dest_lng, None, dest_address) - artifactHelper.addRoute(dest_title, time, dest_address, self.PROGRAM_NAME, self.CAT_DESTINATION, source_lat, source_lng, dest_lat, dest_lng) + artifactHelper.addRoute(dest_title, time, waypointlist, None) except SQLException as ex: # Unable to execute Google map locations SQL query against database. From b2001eb84b2383e6686e618e579f1fbd11d12018 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Thu, 20 Feb 2020 15:40:20 -0500 Subject: [PATCH 13/77] Intial changes for Context and Associated Objects RecentDoc Link files and Adobe MRU associated objects and context viewer support for recent docs. --- .../contextviewer/Bundle.properties-MERGED | 3 ++ .../contextviewer/ContextViewer.java | 32 ++++++++++++++- .../recentactivity/ExtractRegistry.java | 38 +++++++++++++++++ .../recentactivity/RecentDocumentsByLnk.java | 41 ++++++++++++++++++- 4 files changed, 112 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED index 79f4f61bfa..b29e7190fd 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED @@ -3,6 +3,7 @@ ContextViewer.downloadedOn=On ContextViewer.downloadSource=Downloaded from: ContextViewer.downloadURL=URL ContextViewer.email=Email +ContextViewer.file=File ContextViewer.jSourceGoToResultButton.text=Go to Result ContextViewer.jSourceTextLabel.text=jLabel2 ContextViewer.jSourceNameLabel.text=jSourceNameLabel @@ -11,5 +12,7 @@ ContextViewer.message=Message ContextViewer.messageFrom=From ContextViewer.messageOn=On ContextViewer.messageTo=To +ContextViewer.on=On +ContextViewer.recentDocs=Recent Documents: ContextViewer.title=Context ContextViewer.toolTip=Displays context for selected file. diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java index 2e183755f1..1baa412495 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java @@ -287,7 +287,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte */ @NbBundle.Messages({ "ContextViewer.attachmentSource=Attached to: ", - "ContextViewer.downloadSource=Downloaded from: " + "ContextViewer.downloadSource=Downloaded from: ", + "ContextViewer.recentDocs=Recent Documents: " }) private void setSourceFields(BlackboardArtifact associatedArtifact) throws TskCoreException { if (BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE.getTypeID() == associatedArtifact.getArtifactTypeID() @@ -301,6 +302,10 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte setSourceName(Bundle.ContextViewer_downloadSource()); setSourceText(webDownloadArtifactToString(associatedArtifact)); + } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == associatedArtifact.getArtifactTypeID()) { + setSourceName(Bundle.ContextViewer_recentDocs()); + setSourceText(recentDocArtifactToString(associatedArtifact)); + } } @@ -355,6 +360,31 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte return sb.toString(); } + /** + * Returns a display string with recent Doc + * artifact. + * + * @param artifact artifact to get doc from. + * + * @return Display string with download URL and date/time. + * + * @throws TskCoreException + */ + @NbBundle.Messages({ + "ContextViewer.file=File", + "ContextViewer.on=On" + }) + private String recentDocArtifactToString(BlackboardArtifact artifact) throws TskCoreException { + StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN); + Map attributesMap = getAttributesMap(artifact); + + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == artifact.getArtifactTypeID()) { + appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, attributesMap, Bundle.ContextViewer_file()); + appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, Bundle.ContextViewer_on()); + } + return sb.toString(); + } + /** * Returns a abbreviated display string for a message artifact. * diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index a17a9e2628..e1b9d3b362 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -56,6 +56,7 @@ import org.xml.sax.SAXException; import java.nio.file.Path; import java.util.AbstractMap; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Collection; import java.util.Date; @@ -66,6 +67,7 @@ import java.util.Set; import java.util.HashSet; import static java.util.Locale.US; import static java.util.TimeZone.getTimeZone; +import org.apache.commons.io.FilenameUtils; import org.openide.util.Lookup; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; @@ -73,7 +75,9 @@ import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.recentactivity.ShellBagParser.ShellBag; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; import org.sleuthkit.datamodel.BlackboardAttribute; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_ACCESSED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_CREATED; import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_MODIFIED; @@ -1278,6 +1282,11 @@ class ExtractRegistry extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(fileName, bba); + if (bba != null) { + bbartifacts.add(bba); + } + } line = reader.readLine(); } @@ -1288,6 +1297,35 @@ class ExtractRegistry extends Extract { postArtifacts(bbartifacts); } } + + private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); + String fileName = FilenameUtils.getName(filePathName); + String filePath = FilenameUtils.getPath(filePathName); + List sourceFiles; + try { + sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + if (!sourceFiles.isEmpty()) { + for (AbstractFile sourceFile : sourceFiles) { + if (sourceFile.getParentPath().endsWith(filePath)) { + Collection bbattributes2 = new ArrayList<>(); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); + + BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); + if (associatedObjectBba != null) { + return associatedObjectBba; + } + } + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error finding lnk actual file."); //NON-NLS + } + + return null; + } /** * Create the shellbag artifacts from the list of ShellBag objects. diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index 558a29bf8e..a02a77b582 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -23,12 +23,14 @@ package org.sleuthkit.autopsy.recentactivity; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import java.util.Collection; +import org.apache.commons.io.FilenameUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.JLNK; import org.sleuthkit.autopsy.coreutils.JLnkParser; @@ -41,6 +43,8 @@ import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.*; +import static org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT; +import static org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT; /** * Recent documents class that will extract recent documents in the form of .lnk @@ -107,7 +111,7 @@ class RecentDocumentsByLnk extends Extract { } Collection bbattributes = new ArrayList<>(); - String path = lnk.getBestPath(); + String path = FilenameUtils.normalize(lnk.getBestPath(), true); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.parentModuleName.noSpace"), @@ -123,12 +127,47 @@ class RecentDocumentsByLnk extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, recentFile, bbattributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(path, bba); + if (bba != null) { + bbartifacts.add(bba); + } } } + + postArtifacts(bbartifacts); } + private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { + org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); + String fileName = FilenameUtils.getName(filePathName); + String filePath = FilenameUtils.getPath(filePathName); + List sourceFiles; + try { + sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS + if (!sourceFiles.isEmpty()) { + for (AbstractFile sourceFile : sourceFiles) { + if (sourceFile.getParentPath().endsWith(filePath)) { + Collection bbattributes2 = new ArrayList<>(); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); + + BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); + if (associatedObjectBba != null) { + return associatedObjectBba; + } + } + } + } + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Error finding lnk actual file."); //NON-NLS + } + + return null; + } + @Override public void process(Content dataSource, IngestJobContext context, DataSourceIngestModuleProgress progressBar) { this.dataSource = dataSource; From 49bf930794cebf69f75033859e9aa54ec5811889 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Fri, 21 Feb 2020 10:16:04 -0500 Subject: [PATCH 14/77] finished refactoring --- .../datamodel/CentralRepoDbManager.java | 23 +++++++++---------- .../optionspanel/EamDbSettingsDialog.java | 12 +++++++++- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 5df9b445b9..ab2fbfa4c3 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -129,6 +129,17 @@ public class CentralRepoDbManager { return dbSettingsSqlite; } + /** + * Returns if changes to the central repository configuration were + * successfully applied + * + * @return true if the database configuration was successfully changed false + * if it was not + */ + public boolean wasConfigurationChanged() { + return configurationChanged; + } + public boolean createDb() throws CentralRepoException { boolean dbCreated = true; switch (selectedPlatform) { @@ -348,16 +359,4 @@ public class CentralRepoDbManager { return testingStatus; } - - - /** - * Returns if changes to the central repository configuration were - * successfully applied - * - * @return true if the database configuration was successfully changed false - * if it was not - */ - boolean wasConfigurationChanged() { - return configurationChanged; - } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 51659aa21f..6614d90094 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -467,7 +467,7 @@ public class EamDbSettingsDialog extends JDialog { SwingUtilities.invokeLater(() -> { JOptionPane.showMessageDialog(this, Bundle.EamDbSettingsDialog_okButton_errorMsg_text(), - EamDbSettingsDialog_okButton_errorTitle_text(), + Bundle.EamDbSettingsDialog_okButton_errorTitle_text(), JOptionPane.WARNING_MESSAGE); }); } @@ -478,6 +478,16 @@ public class EamDbSettingsDialog extends JDialog { }//GEN-LAST:event_bnOkActionPerformed + /** + * Returns if changes to the central repository configuration were + * successfully applied + * + * @return true if the database configuration was successfully changed false + * if it was not + */ + public boolean wasConfigurationChanged() { + return manager.wasConfigurationChanged(); + } private void bnCancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnCancelActionPerformed dispose(); From 851a3308ad5bb12945a484b48a641ee25cc20de7 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Fri, 21 Feb 2020 13:51:16 -0500 Subject: [PATCH 15/77] working through initial central repository enable --- .../datamodel/CentralRepoDbManager.java | 23 ++++++------- .../datamodel/SqliteCentralRepoSettings.java | 10 +++++- .../eventlisteners/Installer.java | 34 +++++++++++++++++-- .../optionspanel/EamDbSettingsDialog.java | 5 +-- 4 files changed, 55 insertions(+), 17 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index ab2fbfa4c3..60a644f411 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -18,16 +18,11 @@ import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; -public class CentralRepoDbManager { - private static final String CENTRAL_REPO_DB_NAME = "central_repository"; - private static final String CENTRAL_REPO_SQLITE_EXT = ".db"; - +public class CentralRepoDbManager { private static final Logger logger = Logger.getLogger(CentralRepoDbManager.class.getName()); + + private static final String CENTRAL_REPO_DB_NAME = "central_repository"; - public static String getDefaultSqliteDbName() { - return CENTRAL_REPO_DB_NAME + CENTRAL_REPO_SQLITE_EXT; - } - /** * Upgrade the current Central Reposity schema to the newest version. If the * upgrade fails, the Central Repository will be disabled and the current @@ -36,10 +31,9 @@ public class CentralRepoDbManager { @NbBundle.Messages(value = {"EamDbUtil.centralRepoDisabled.message= The Central Repository has been disabled.", "EamDbUtil.centralRepoUpgradeFailed.message=Failed to upgrade Central Repository.", "EamDbUtil.centralRepoConnectionFailed.message=Unable to connect to Central Repository.", "EamDbUtil.exclusiveLockAquisitionFailure.message=Unable to acquire exclusive lock for Central Repository."}) public static void upgradeDatabase() throws CentralRepoException { if (!CentralRepository.isEnabled()) { - // TODO -// EamDbSettingsDialog dialog = new EamDbSettingsDialog(); -// dialog.promptUserForSetup(); + return; } + CentralRepository db = null; CoordinationService.Lock lock = null; //get connection @@ -129,6 +123,11 @@ public class CentralRepoDbManager { return dbSettingsSqlite; } + public void setupDefaultSqliteSettings() { + selectedPlatform = CentralRepoPlatforms.SQLITE; + dbSettingsSqlite.setupDefaultSettings(); + } + /** * Returns if changes to the central repository configuration were * successfully applied @@ -313,7 +312,7 @@ public class CentralRepoDbManager { break; case SQLITE: File databasePath = new File(tfDatabasePath); - dbSettingsSqlite.setDbName(getDefaultSqliteDbName()); + dbSettingsSqlite.setDbName(SqliteCentralRepoSettings.DEFAULT_DBNAME); dbSettingsSqlite.setDbDirectory(databasePath.getPath()); break; default: diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java index 3b2a424c4a..b0ffee2ed2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java @@ -42,8 +42,8 @@ import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo */ public final class SqliteCentralRepoSettings { + public final static String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS private final static Logger LOGGER = Logger.getLogger(SqliteCentralRepoSettings.class.getName()); - private final static String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS private final static String DEFAULT_DBDIRECTORY = PlatformUtil.getUserDirectory() + File.separator + "central_repository"; // NON-NLS private final static String JDBC_DRIVER = "org.sqlite.JDBC"; // NON-NLS private final static String JDBC_BASE_URI = "jdbc:sqlite:"; // NON-NLS @@ -89,6 +89,14 @@ public final class SqliteCentralRepoSettings { this.bulkThreshold = RdbmsCentralRepo.DEFAULT_BULK_THRESHHOLD; } } + + /** + * sets database directory and name to defaults + */ + public void setupDefaultSettings() { + dbName = DEFAULT_DBNAME; + dbDirectory = DEFAULT_DBDIRECTORY; + } public void saveSettings() { createDbDirectory(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 73ab88d87c..d6f0df3687 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -28,6 +28,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.coreutils.ModuleSettings; /** * Install event listeners during module initialization @@ -52,7 +53,14 @@ public class Installer extends ModuleInstall { super(); } - @NbBundle.Messages({"Installer.centralRepoUpgradeFailed.title=Central repository disabled"}) + @NbBundle.Messages({ + "Installer.centralRepoUpgradeFailed.title=Central repository disabled", + "Installer.initialCreateSqlite.title=Create Sqlite Central Repository?", + "Installer.initialCreateSqlite.message=The central repository allows a user to find matching artifacts both across cases " + + "and across data sources in the same case. Having data in the central repository is useful for file discovery. Would you " + + "like to create the default Central Repository now? If you choose not to at this time, this setting can be changed in the " + + "options panel." + }) @Override public void restored() { Case.addPropertyChangeListener(pcl); @@ -60,7 +68,29 @@ public class Installer extends ModuleInstall { // Perform the database upgrade and inform the user if it fails try { - CentralRepoDbManager.upgradeDatabase(); + String initialized = ModuleSettings.getConfigSetting("CentralRepository", "initialized"); + if (!Boolean.parseBoolean(initialized)) { + String dialogText = "

" + + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.message") + + "

"; + + boolean setupSqlite = !RuntimeProperties.runningWithGUI() || + JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), + dialogText, + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.title"), + JOptionPane.YES_NO_OPTION); + + if (setupSqlite) { + CentralRepoDbManager manager = new CentralRepoDbManager(); + manager.setupDefaultSqliteSettings(); + manager.saveNewCentralRepo(); + } + + ModuleSettings.setConfigSetting("CentralRepository", "initialized", "true"); + } + else { + CentralRepoDbManager.upgradeDatabase(); + } } catch (CentralRepoException ex) { if (RuntimeProperties.runningWithGUI()) { WindowManager.getDefault().invokeWhenUIReady(() -> { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 6614d90094..c45d05bb68 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -44,6 +44,7 @@ import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoPlatforms; import org.sleuthkit.autopsy.centralrepository.datamodel.DatabaseTestResult; +import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; /** * Configuration dialog for Central Repository database settings. @@ -84,7 +85,7 @@ public class EamDbSettingsDialog extends JDialog { if (pathname.isDirectory()) { return true; } - return pathname.getName().equalsIgnoreCase(CentralRepoDbManager.getDefaultSqliteDbName()); + return pathname.getName().equalsIgnoreCase(SqliteCentralRepoSettings.DEFAULT_DBNAME); } @Override @@ -500,7 +501,7 @@ public class EamDbSettingsDialog extends JDialog { }//GEN-LAST:event_cbDatabaseTypeActionPerformed private void updateFullDbPath() { - dataBaseFileTextArea.setText(tfDatabasePath.getText() + File.separator + manager.getDefaultSqliteDbName()); + dataBaseFileTextArea.setText(tfDatabasePath.getText() + File.separator + SqliteCentralRepoSettings.DEFAULT_DBNAME); dataBaseFileTextArea.setCaretPosition(dataBaseFileTextArea.getText().length()); } From 1b18e39dcfaa31b851799bf8441e4d6556c747c5 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Fri, 21 Feb 2020 16:08:26 -0500 Subject: [PATCH 16/77] created central repo on first load --- .../datamodel/CentralRepoDbManager.java | 3 + .../eventlisteners/Installer.java | 120 ++++++++++++------ 2 files changed, 85 insertions(+), 38 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 60a644f411..320887b74d 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -255,6 +255,9 @@ public class CentralRepoDbManager { break; case SQLITE: // save the new SQLite settings + logger.info(String.format("Attempting to set up sqlite database at path: %s with filename: %s", + dbSettingsSqlite.getDbDirectory(), dbSettingsSqlite.getDbName())); + dbSettingsSqlite.saveSettings(); // Load those newly saved settings into the sqlite db manager instance // in case we are still using the same instance. diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index d6f0df3687..22d2a88836 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -18,8 +18,12 @@ */ package org.sleuthkit.autopsy.centralrepository.eventlisteners; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; import org.openide.modules.ModuleInstall; +import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; @@ -55,55 +59,95 @@ public class Installer extends ModuleInstall { @NbBundle.Messages({ "Installer.centralRepoUpgradeFailed.title=Central repository disabled", - "Installer.initialCreateSqlite.title=Create Sqlite Central Repository?", - "Installer.initialCreateSqlite.message=The central repository allows a user to find matching artifacts both across cases " + - "and across data sources in the same case. Having data in the central repository is useful for file discovery. Would you " + - "like to create the default Central Repository now? If you choose not to at this time, this setting can be changed in the " + - "options panel." + "Installer.initialCreateSqlite.title=Enable Central Repository?", + "Installer.initialCreateSqlite.message=The Central Repository is not enabled. Would you like to enable it? " + + "It will store information about all hashes and identifiers that you process. You can use this to ignore previously " + + "seen files and make connections between cases." }) @Override public void restored() { Case.addPropertyChangeListener(pcl); ieListener.installListeners(); - // Perform the database upgrade and inform the user if it fails - try { - String initialized = ModuleSettings.getConfigSetting("CentralRepository", "initialized"); - if (!Boolean.parseBoolean(initialized)) { - String dialogText = "

" + - NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.message") + - "

"; - - boolean setupSqlite = !RuntimeProperties.runningWithGUI() || - JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), - dialogText, - NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.title"), - JOptionPane.YES_NO_OPTION); - - if (setupSqlite) { - CentralRepoDbManager manager = new CentralRepoDbManager(); - manager.setupDefaultSqliteSettings(); - manager.saveNewCentralRepo(); - } - - ModuleSettings.setConfigSetting("CentralRepository", "initialized", "true"); - } - else { - CentralRepoDbManager.upgradeDatabase(); - } - } catch (CentralRepoException ex) { + String initialized = ModuleSettings.getConfigSetting("CentralRepository", "initialized"); + + // if central repository hasn't been previously initialized, initialize it + if (!Boolean.parseBoolean(initialized)) { + // if running with a GUI, prompt the user if (RuntimeProperties.runningWithGUI()) { - WindowManager.getDefault().invokeWhenUIReady(() -> { - JOptionPane.showMessageDialog(null, - ex.getUserMessage(), - NbBundle.getMessage(this.getClass(), - "Installer.centralRepoUpgradeFailed.title"), - JOptionPane.ERROR_MESSAGE); - }); + try { + SwingUtilities.invokeAndWait(() -> { + try { + String dialogText = "

" + + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.message") + + "

"; + + if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), + dialogText, + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.title"), + JOptionPane.YES_NO_OPTION)) { + + setupDefaultSqlite(); + } + } catch (CentralRepoException ex) { + LOGGER.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); + + reportUpgradeError(ex); + } + }); + } catch (Exception ex) { + LOGGER.log(Level.SEVERE, "There was an error while running the swing utility invoke later while creating the central repository database", ex); + } + } // if no GUI, just initialize + else { + try { + setupDefaultSqlite(); + } catch (CentralRepoException ex) { + LOGGER.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); + + reportUpgradeError(ex); + } + } + + ModuleSettings.setConfigSetting("CentralRepository", "initialized", "true"); + } + + // now run regular module startup code + try { + CentralRepoDbManager.upgradeDatabase(); + } catch (CentralRepoException ex) { + LOGGER.log(Level.SEVERE, "There was an error while upgrading the central repository database", ex); + if (RuntimeProperties.runningWithGUI()) { + reportUpgradeError(ex); } } } + private void setupDefaultSqlite() throws CentralRepoException { + CentralRepoDbUtil.setUseCentralRepo(true); + CentralRepoDbManager manager = new CentralRepoDbManager(); + manager.setupDefaultSqliteSettings(); + manager.createDb(); + manager.saveNewCentralRepo(); + } + + private void reportUpgradeError(CentralRepoException ex) { + try { + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog(null, + ex.getUserMessage(), + NbBundle.getMessage(this.getClass(), + "Installer.centralRepoUpgradeFailed.title"), + JOptionPane.ERROR_MESSAGE); + }); + } catch (Exception e) { + LOGGER.warning("There was an error while running the swing utility invoke later while displaying an error " + + "for creating the central repository database: " + + e.getMessage() + System.lineSeparator() + e.getStackTrace()); + } + + } + @Override public boolean closing() { //platform about to close From 22131f4491dde9a03543d7392550ba83c12d62ad Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 07:54:11 -0500 Subject: [PATCH 17/77] updated formatting in central repo initialization message --- .../eventlisteners/Installer.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 22d2a88836..8f96140837 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -60,9 +60,9 @@ public class Installer extends ModuleInstall { @NbBundle.Messages({ "Installer.centralRepoUpgradeFailed.title=Central repository disabled", "Installer.initialCreateSqlite.title=Enable Central Repository?", - "Installer.initialCreateSqlite.message=The Central Repository is not enabled. Would you like to enable it? " + - "It will store information about all hashes and identifiers that you process. You can use this to ignore previously " + - "seen files and make connections between cases." + "Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to?", + "Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. " + + "You can use this to ignore previously seen files and make connections between cases." }) @Override public void restored() { @@ -78,9 +78,13 @@ public class Installer extends ModuleInstall { try { SwingUtilities.invokeAndWait(() -> { try { - String dialogText = "

" - + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.message") - + "

"; + String dialogText = + "" + + "
" + + "

" + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.messageHeader") + "

" + + "

" + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.messageDesc") + "

" + + "
" + + ""; if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), dialogText, From fcf85ee0df4e856794a4946e7d9b914aaa5b4726 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 09:19:45 -0500 Subject: [PATCH 18/77] fix for exception on method --- .../centralrepository/datamodel/CentralRepoDbManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 33a69fef97..d7061719f2 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -148,7 +148,7 @@ public class CentralRepoDbManager { } } - private RdbmsCentralRepoFactory getDbFactory() { + private RdbmsCentralRepoFactory getDbFactory() throws CentralRepoException { switch (selectedPlatform) { case POSTGRESQL: return new RdbmsCentralRepoFactory(selectedPlatform, dbSettingsPostgres); case SQLITE: return new RdbmsCentralRepoFactory(selectedPlatform, dbSettingsSqlite); From bf4c252fed6792e0197d5eae9a678405328913e3 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 10:03:52 -0500 Subject: [PATCH 19/77] central repo code cleanup --- .../datamodel/CentralRepoDbManager.java | 136 ++++++++---------- ...ttings.java => CentralRepoDbSettings.java} | 4 +- .../PostgresCentralRepoSettings.java | 2 +- .../datamodel/SqliteCentralRepoSettings.java | 2 +- .../optionspanel/EamDbSettingsDialog.java | 5 +- 5 files changed, 71 insertions(+), 78 deletions(-) rename Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/{CentralRepoSettings.java => CentralRepoDbSettings.java} (92%) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index d7061719f2..7bcd05af12 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -17,10 +17,10 @@ import org.sleuthkit.autopsy.centralrepository.optionspanel.EamDbSettingsDialog; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; +public class CentralRepoDbManager { -public class CentralRepoDbManager { private static final Logger logger = Logger.getLogger(CentralRepoDbManager.class.getName()); - + private static final String CENTRAL_REPO_DB_NAME = "central_repository"; /** @@ -33,7 +33,7 @@ public class CentralRepoDbManager { if (!CentralRepository.isEnabled()) { return; } - + CentralRepository db = null; CoordinationService.Lock lock = null; //get connection @@ -93,19 +93,15 @@ public class CentralRepoDbManager { throw ex; } } - - - - + private DatabaseTestResult testingStatus; private CentralRepoPlatforms selectedPlatform; private PostgresCentralRepoSettings dbSettingsPostgres; private SqliteCentralRepoSettings dbSettingsSqlite; - + private boolean configurationChanged = false; - - + public CentralRepoDbManager() { dbSettingsPostgres = new PostgresCentralRepoSettings(); dbSettingsSqlite = new SqliteCentralRepoSettings(); @@ -122,12 +118,12 @@ public class CentralRepoDbManager { public SqliteCentralRepoSettings getDbSettingsSqlite() { return dbSettingsSqlite; } - + public void setupDefaultSqliteSettings() { selectedPlatform = CentralRepoPlatforms.SQLITE; dbSettingsSqlite.setupDefaultSettings(); } - + /** * Returns if changes to the central repository configuration were * successfully applied @@ -139,20 +135,43 @@ public class CentralRepoDbManager { return configurationChanged; } - - private CentralRepoSettings getSelectedSettings() throws CentralRepoException { + private CentralRepoDbSettings getSelectedSettings() throws CentralRepoException { switch (selectedPlatform) { - case POSTGRESQL: return dbSettingsPostgres; - case SQLITE: return dbSettingsSqlite; - default: throw new CentralRepoException("Unknown database type: " + selectedPlatform); + case POSTGRESQL: + return dbSettingsPostgres; + case SQLITE: + return dbSettingsSqlite; + case DISABLED: + return null; + default: + throw new CentralRepoException("Unknown database type: " + selectedPlatform); } } private RdbmsCentralRepoFactory getDbFactory() throws CentralRepoException { switch (selectedPlatform) { - case POSTGRESQL: return new RdbmsCentralRepoFactory(selectedPlatform, dbSettingsPostgres); - case SQLITE: return new RdbmsCentralRepoFactory(selectedPlatform, dbSettingsSqlite); - default: throw new CentralRepoException("Unknown database type: " + selectedPlatform); + case POSTGRESQL: + return new RdbmsCentralRepoFactory(selectedPlatform, dbSettingsPostgres); + case SQLITE: + return new RdbmsCentralRepoFactory(selectedPlatform, dbSettingsSqlite); + case DISABLED: + return null; + default: + throw new CentralRepoException("Unknown database type: " + selectedPlatform); + } + } + + private String getCurrentSettingsString() throws CentralRepoException { + switch (selectedPlatform) { + case POSTGRESQL: + return String.format("[db type: postgres, host: %s:%d, db name: %s, username: %s]", + dbSettingsPostgres.getHost(), dbSettingsPostgres.getPort(), dbSettingsPostgres.getDbName(), dbSettingsPostgres.getUserName()); + case SQLITE: + return String.format("[db type: sqlite, directory: %s, name: %s]", dbSettingsSqlite.getDbDirectory(), dbSettingsSqlite.getDbName()); + case DISABLED: + return "[db type: disabled]"; + default: + throw new CentralRepoException("Unknown database type: " + selectedPlatform); } } @@ -160,7 +179,7 @@ public class CentralRepoDbManager { boolean result = false; boolean dbCreated = true; - CentralRepoSettings selectedDbSettings = getSelectedSettings(); + CentralRepoDbSettings selectedDbSettings = getSelectedSettings(); if (!selectedDbSettings.verifyDatabaseExists()) { dbCreated = selectedDbSettings.createDatabase(); @@ -170,20 +189,9 @@ public class CentralRepoDbManager { RdbmsCentralRepoFactory centralRepoSchemaFactory = getDbFactory(); result = centralRepoSchemaFactory.initializeDatabaseSchema() - && centralRepoSchemaFactory.insertDefaultDatabaseContent(); + && centralRepoSchemaFactory.insertDefaultDatabaseContent(); } catch (CentralRepoException ex) { - String message = ""; - switch (selectedPlatform) { - case POSTGRESQL: - message = String.format("Unable to create Postgres database for Central Repository at %s:%d with db name: %s and username %s", - dbSettingsPostgres.getHost(), dbSettingsPostgres.getPort(), dbSettingsPostgres.getDbName(), dbSettingsPostgres.getUserName()); - break; - case SQLITE: - message = "Unable to create Sqlite database for Central Repository at " + dbSettingsSqlite.getDbDirectory(); - break; - } - - logger.log(Level.SEVERE, message, ex); + logger.log(Level.SEVERE, "Unable to create database for central repository " + getCurrentSettingsString(), ex); throw new CentralRepoException("Unable to create Postgres database for Central Repository."); } } @@ -203,7 +211,6 @@ public class CentralRepoDbManager { return true; } - /** * saves a new central repository based on current settings */ @@ -234,39 +241,23 @@ public class CentralRepoDbManager { CentralRepoPlatforms.setSelectedPlatform(selectedPlatform.name()); CentralRepoPlatforms.saveSelectedPlatform(); + CentralRepoDbSettings selectedDbSettings = getSelectedSettings(); + + // save the new settings + selectedDbSettings.saveSettings(); + // Load those newly saved settings into the postgres db manager instance + // in case we are still using the same instance. switch (selectedPlatform) { case POSTGRESQL: - // save the new PostgreSQL settings - dbSettingsPostgres.saveSettings(); - // Load those newly saved settings into the postgres db manager instance - // in case we are still using the same instance. + case SQLITE: try { + logger.info("Creating central repo db with settings: " + getCurrentSettingsString()); CentralRepository.getInstance().updateSettings(); configurationChanged = true; } catch (CentralRepoException ex) { logger.log(Level.SEVERE, Bundle.CentralRepoDbManager_connectionErrorMsg_text(), ex); //NON-NLS return; } - - break; - case SQLITE: - // save the new SQLite settings - logger.info(String.format("Attempting to set up sqlite database at path: %s with filename: %s", - dbSettingsSqlite.getDbDirectory(), dbSettingsSqlite.getDbName())); - - dbSettingsSqlite.saveSettings(); - // Load those newly saved settings into the sqlite db manager instance - // in case we are still using the same instance. - try { - CentralRepository.getInstance().updateSettings(); - configurationChanged = true; - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, Bundle.CentralRepoDbManager_connectionErrorMsg_text(), ex); //NON-NLS - return; - } - break; - case DISABLED: - break; } } @@ -282,42 +273,39 @@ public class CentralRepoDbManager { testingStatus = DatabaseTestResult.UNTESTED; } - - public void setSelectedPlatform(CentralRepoPlatforms newSelected) { selectedPlatform = newSelected; testingStatus = DatabaseTestResult.UNTESTED; } - - + /** * Tests whether or not the database settings are valid. * * @return True or false. */ - public boolean testDatabaseSettingsAreValid ( + public boolean testDatabaseSettingsAreValid( String tbDbHostname, String tbDbPort, String tbDbUsername, String tfDatabasePath, String jpDbPassword) throws CentralRepoException, NumberFormatException { - + boolean result = true; StringBuilder guidanceText = new StringBuilder(); switch (selectedPlatform) { case POSTGRESQL: - dbSettingsPostgres.setHost(tbDbHostname); - dbSettingsPostgres.setPort(Integer.parseInt(tbDbPort)); - dbSettingsPostgres.setDbName(CENTRAL_REPO_DB_NAME); - dbSettingsPostgres.setUserName(tbDbUsername); - dbSettingsPostgres.setPassword(jpDbPassword); + dbSettingsPostgres.setHost(tbDbHostname); + dbSettingsPostgres.setPort(Integer.parseInt(tbDbPort)); + dbSettingsPostgres.setDbName(CENTRAL_REPO_DB_NAME); + dbSettingsPostgres.setUserName(tbDbUsername); + dbSettingsPostgres.setPassword(jpDbPassword); break; case SQLITE: - File databasePath = new File(tfDatabasePath); - dbSettingsSqlite.setDbName(SqliteCentralRepoSettings.DEFAULT_DBNAME); - dbSettingsSqlite.setDbDirectory(databasePath.getPath()); + File databasePath = new File(tfDatabasePath); + dbSettingsSqlite.setDbName(SqliteCentralRepoSettings.DEFAULT_DBNAME); + dbSettingsSqlite.setDbDirectory(databasePath.getPath()); break; default: throw new IllegalStateException("Central Repo has an unknown selected platform: " + selectedPlatform); } - + return result; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java similarity index 92% rename from Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoSettings.java rename to Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java index d29b398df1..fd4fec0e13 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java @@ -9,8 +9,10 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; * * @author gregd */ -public interface CentralRepoSettings { +public interface CentralRepoDbSettings { + public void saveSettings(); + boolean createDatabase(); boolean deleteDatabase(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java index 5f0de140d5..cfdd648ddc 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java @@ -40,7 +40,7 @@ import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo * NOTE: This is public scope because the options panel calls it directly to * set/get */ -public final class PostgresCentralRepoSettings implements CentralRepoSettings { +public final class PostgresCentralRepoSettings implements CentralRepoDbSettings { private final static Logger LOGGER = Logger.getLogger(PostgresCentralRepoSettings.class.getName()); private final static String DEFAULT_HOST = ""; // NON-NLS diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java index 39c9c6a154..5e88404b0f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java @@ -37,7 +37,7 @@ import org.sleuthkit.autopsy.coreutils.PlatformUtil; * NOTE: This is public scope because the options panel calls it directly to * set/get */ -public final class SqliteCentralRepoSettings implements CentralRepoSettings { +public final class SqliteCentralRepoSettings implements CentralRepoDbSettings { public final static String DEFAULT_DBNAME = "central_repository.db"; // NON-NLS private final static Logger LOGGER = Logger.getLogger(SqliteCentralRepoSettings.class.getName()); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 319ac9cfda..db657d7fab 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -158,6 +158,8 @@ public class EamDbSettingsDialog extends JDialog { Bundle.EamDbSettingsDialog_okButton_createDbError_title(), JOptionPane.WARNING_MESSAGE); } + + valid(); } } @@ -456,7 +458,8 @@ public class EamDbSettingsDialog extends JDialog { private void bnOkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bnOkActionPerformed setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); manager.testStatus(); - + valid(); + boolean testedOk = promptTestStatusWarnings(); if (!testedOk) { setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); From 367bd69bddcc41a867e10128d8c27081bd8a3a4b Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 10:11:16 -0500 Subject: [PATCH 20/77] central repo code cleanup --- .../datamodel/CentralRepoDbManager.java | 18 ++---------------- .../datamodel/PostgresCentralRepoSettings.java | 6 ++++++ .../datamodel/SqliteCentralRepoSettings.java | 4 ++++ 3 files changed, 12 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 7bcd05af12..c800f27f1a 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -161,20 +161,6 @@ public class CentralRepoDbManager { } } - private String getCurrentSettingsString() throws CentralRepoException { - switch (selectedPlatform) { - case POSTGRESQL: - return String.format("[db type: postgres, host: %s:%d, db name: %s, username: %s]", - dbSettingsPostgres.getHost(), dbSettingsPostgres.getPort(), dbSettingsPostgres.getDbName(), dbSettingsPostgres.getUserName()); - case SQLITE: - return String.format("[db type: sqlite, directory: %s, name: %s]", dbSettingsSqlite.getDbDirectory(), dbSettingsSqlite.getDbName()); - case DISABLED: - return "[db type: disabled]"; - default: - throw new CentralRepoException("Unknown database type: " + selectedPlatform); - } - } - public boolean createDb() throws CentralRepoException { boolean result = false; boolean dbCreated = true; @@ -191,7 +177,7 @@ public class CentralRepoDbManager { result = centralRepoSchemaFactory.initializeDatabaseSchema() && centralRepoSchemaFactory.insertDefaultDatabaseContent(); } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Unable to create database for central repository " + getCurrentSettingsString(), ex); + logger.log(Level.SEVERE, "Unable to create database for central repository with settings " + selectedDbSettings, ex); throw new CentralRepoException("Unable to create Postgres database for Central Repository."); } } @@ -251,7 +237,7 @@ public class CentralRepoDbManager { case POSTGRESQL: case SQLITE: try { - logger.info("Creating central repo db with settings: " + getCurrentSettingsString()); + logger.info("Creating central repo db with settings: " + selectedDbSettings); CentralRepository.getInstance().updateSettings(); configurationChanged = true; } catch (CentralRepoException ex) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java index cfdd648ddc..476b67dbc2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/PostgresCentralRepoSettings.java @@ -64,6 +64,12 @@ public final class PostgresCentralRepoSettings implements CentralRepoDbSettings loadSettings(); } + @Override + public String toString() { + return String.format("PostgresCentralRepoSettings: [db type: postgres, host: %s:%d, db name: %s, username: %s]", + getHost(), getPort(), getDbName(), getUserName()); + } + public void loadSettings() { host = ModuleSettings.getConfigSetting("CentralRepository", "db.postgresql.host"); // NON-NLS if (host == null || host.isEmpty()) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java index 5e88404b0f..675a164972 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/SqliteCentralRepoSettings.java @@ -81,6 +81,10 @@ public final class SqliteCentralRepoSettings implements CentralRepoDbSettings { } } + public String toString() { + return String.format("SqliteCentralRepoSettings: [db type: sqlite, directory: %s, name: %s]", getDbDirectory(), getDbName()); + } + /** * sets database directory and name to defaults */ From 8b09842bb50fb2bb086a9e9bff7f990edb070a9e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 11:09:25 -0500 Subject: [PATCH 21/77] fix for licenses on new files in central repo --- .../datamodel/CentralRepoDbManager.java | 19 ++++++++++++++++--- .../datamodel/CentralRepoDbSettings.java | 19 ++++++++++++++++--- .../datamodel/DatabaseTestResult.java | 19 ++++++++++++++++--- .../netbeans/core/startup/Bundle.properties | 4 ++-- .../core/windows/view/ui/Bundle.properties | 6 +++--- 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index c800f27f1a..697a468a23 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Central Repository + * + * Copyright 2015-2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.centralrepository.datamodel; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java index fd4fec0e13..de568c7553 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Central Repository + * + * Copyright 2015-2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.centralrepository.datamodel; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java index d7a13b6041..42df359673 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java @@ -1,7 +1,20 @@ /* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. + * Central Repository + * + * Copyright 2015-2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.sleuthkit.autopsy.centralrepository.datamodel; 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 4f645919d3..b20ccf5912 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 -#Fri, 14 Feb 2020 12:16:52 -0500 +#Tue, 12 Nov 2019 17:21:46 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.14.0 +currentVersion=Autopsy 4.13.0 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 627464541f..998d3f715c 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,4 +1,4 @@ #Updated by build script -#Fri, 14 Feb 2020 12:16:52 -0500 -CTL_MainWindow_Title=Autopsy 4.14.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.14.0 +#Tue, 12 Nov 2019 17:21:46 -0500 +CTL_MainWindow_Title=Autopsy 4.13.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 From 0004afacd12a4f7a697ccfdf2c9c5810632107e2 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 13:05:36 -0500 Subject: [PATCH 22/77] some more code cleanup --- .../datamodel/CentralRepoDbManager.java | 197 +++++++++--------- .../datamodel/CentralRepoDbSettings.java | 2 +- .../datamodel/DatabaseTestResult.java | 3 + .../eventlisteners/Installer.java | 5 +- .../optionspanel/EamDbSettingsDialog.java | 25 +-- 5 files changed, 117 insertions(+), 115 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 697a468a23..a6b0003c35 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -18,18 +18,16 @@ */ package org.sleuthkit.autopsy.centralrepository.datamodel; -import java.awt.Cursor; import java.io.File; import java.sql.SQLException; import java.util.logging.Level; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; import org.openide.util.NbBundle; -import org.openide.windows.WindowManager; -import org.sleuthkit.autopsy.centralrepository.optionspanel.EamDbSettingsDialog; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; import org.sleuthkit.autopsy.coreutils.Logger; +/** + * Contains business logic for saving and validating settings for central repo + */ public class CentralRepoDbManager { private static final Logger logger = Logger.getLogger(CentralRepoDbManager.class.getName()); @@ -49,69 +47,85 @@ public class CentralRepoDbManager { CentralRepository db = null; CoordinationService.Lock lock = null; + //get connection try { + db = CentralRepository.getInstance(); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); + onUpgradeError("Error updating central repository, unable to make connection", + Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } + + //get lock necessary for upgrade + if (db != null) { try { - db = CentralRepository.getInstance(); + // This may return null if locking isn't supported, which is fine. It will + // throw an exception if locking is supported but we can't get the lock + // (meaning the database is in use by another user) + lock = db.getExclusiveMultiUserDbLock(); + //perform upgrade } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); - throw new CentralRepoException("Error updating central repository, unable to make connection", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + logger.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); + onUpgradeError("Error updating central repository, unable to acquire exclusive lock", + Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); } - //get lock necessary for upgrade - if (db != null) { - try { - // This may return null if locking isn't supported, which is fine. It will - // throw an exception if locking is supported but we can't get the lock - // (meaning the database is in use by another user) - lock = db.getExclusiveMultiUserDbLock(); - //perform upgrade - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); - throw new CentralRepoException("Error updating central repository, unable to acquire exclusive lock", Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } - try { - db.upgradeSchema(); - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository", ex); - throw new CentralRepoException("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } catch (SQLException ex) { - logger.log(Level.SEVERE, "Error updating central repository", ex); - throw new CentralRepoException("Error updating central repository", Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } catch (IncompatibleCentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository", ex); - throw new CentralRepoException("Error updating central repository", ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } finally { - if (lock != null) { - try { - lock.release(); - } catch (CoordinationService.CoordinationServiceException ex) { - logger.log(Level.SEVERE, "Error releasing database lock", ex); - } + + try { + db.upgradeSchema(); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository", ex); + onUpgradeError("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } catch (SQLException ex) { + logger.log(Level.SEVERE, "Error updating central repository", ex); + onUpgradeError("Error updating central repository", + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } catch (IncompatibleCentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository", ex); + onUpgradeError("Error updating central repository", + ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } finally { + if (lock != null) { + try { + lock.release(); + } catch (CoordinationService.CoordinationServiceException ex) { + logger.log(Level.SEVERE, "Error releasing database lock", ex); } } - } else { - throw new CentralRepoException("Unable to connect to database", Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message()); } - } catch (CentralRepoException ex) { - // Disable the central repo and clear the current settings. - try { - if (null != CentralRepository.getInstance()) { - CentralRepository.getInstance().shutdownConnections(); - } - } catch (CentralRepoException ex2) { - logger.log(Level.SEVERE, "Error shutting down central repo connection pool", ex2); - } - CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.DISABLED.name()); - CentralRepoPlatforms.saveSelectedPlatform(); - throw ex; + } else { + onUpgradeError("Unable to connect to database", + Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), null); } } + + private static void onUpgradeError(String message, String desc, Exception innerException) throws CentralRepoException { + // Disable the central repo and clear the current settings. + try { + if (null != CentralRepository.getInstance()) { + CentralRepository.getInstance().shutdownConnections(); + } + } catch (CentralRepoException ex2) { + logger.log(Level.SEVERE, "Error shutting down central repo connection pool", ex2); + } + CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.DISABLED.name()); + CentralRepoPlatforms.saveSelectedPlatform(); + if (innerException == null) { + throw new CentralRepoException(message, desc); + } + else { + throw new CentralRepoException(message, desc, innerException); + } + } + + + private DatabaseTestResult testingStatus; private CentralRepoPlatforms selectedPlatform; - private PostgresCentralRepoSettings dbSettingsPostgres; - private SqliteCentralRepoSettings dbSettingsSqlite; + private final PostgresCentralRepoSettings dbSettingsPostgres; + private final SqliteCentralRepoSettings dbSettingsSqlite; private boolean configurationChanged = false; @@ -191,7 +205,7 @@ public class CentralRepoDbManager { && centralRepoSchemaFactory.insertDefaultDatabaseContent(); } catch (CentralRepoException ex) { logger.log(Level.SEVERE, "Unable to create database for central repository with settings " + selectedDbSettings, ex); - throw new CentralRepoException("Unable to create Postgres database for Central Repository."); + throw ex; } } if (!result) { @@ -246,17 +260,15 @@ public class CentralRepoDbManager { selectedDbSettings.saveSettings(); // Load those newly saved settings into the postgres db manager instance // in case we are still using the same instance. - switch (selectedPlatform) { - case POSTGRESQL: - case SQLITE: - try { - logger.info("Creating central repo db with settings: " + selectedDbSettings); - CentralRepository.getInstance().updateSettings(); - configurationChanged = true; - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, Bundle.CentralRepoDbManager_connectionErrorMsg_text(), ex); //NON-NLS - return; - } + if (selectedPlatform == CentralRepoPlatforms.POSTGRESQL || selectedPlatform == CentralRepoPlatforms.SQLITE) { + try { + logger.info("Creating central repo db with settings: " + selectedDbSettings); + CentralRepository.getInstance().updateSettings(); + configurationChanged = true; + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, Bundle.CentralRepoDbManager_connectionErrorMsg_text(), ex); //NON-NLS + return; + } } } @@ -285,9 +297,6 @@ public class CentralRepoDbManager { public boolean testDatabaseSettingsAreValid( String tbDbHostname, String tbDbPort, String tbDbUsername, String tfDatabasePath, String jpDbPassword) throws CentralRepoException, NumberFormatException { - boolean result = true; - StringBuilder guidanceText = new StringBuilder(); - switch (selectedPlatform) { case POSTGRESQL: dbSettingsPostgres.setHost(tbDbHostname); @@ -305,41 +314,39 @@ public class CentralRepoDbManager { throw new IllegalStateException("Central Repo has an unknown selected platform: " + selectedPlatform); } - return result; + return true; } public DatabaseTestResult testStatus() { - switch (selectedPlatform) { - case POSTGRESQL: - if (dbSettingsPostgres.verifyConnection()) { - if (dbSettingsPostgres.verifyDatabaseExists()) { - if (dbSettingsPostgres.verifyDatabaseSchema()) { - testingStatus = DatabaseTestResult.TESTEDOK; - } else { - testingStatus = DatabaseTestResult.SCHEMA_INVALID; - } - } else { - testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; - } - } else { - testingStatus = DatabaseTestResult.CONNECTION_FAILED; - } - break; - case SQLITE: - if (dbSettingsSqlite.dbFileExists()) { - if (dbSettingsSqlite.verifyConnection()) { - if (dbSettingsSqlite.verifyDatabaseSchema()) { - testingStatus = DatabaseTestResult.TESTEDOK; - } else { - testingStatus = DatabaseTestResult.SCHEMA_INVALID; - } + if (selectedPlatform == CentralRepoPlatforms.POSTGRESQL) { + if (dbSettingsPostgres.verifyConnection()) { + if (dbSettingsPostgres.verifyDatabaseExists()) { + if (dbSettingsPostgres.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; } else { testingStatus = DatabaseTestResult.SCHEMA_INVALID; } } else { testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; } - break; + } else { + testingStatus = DatabaseTestResult.CONNECTION_FAILED; + } + } + else if (selectedPlatform == CentralRepoPlatforms.SQLITE) { + if (dbSettingsSqlite.dbFileExists()) { + if (dbSettingsSqlite.verifyConnection()) { + if (dbSettingsSqlite.verifyDatabaseSchema()) { + testingStatus = DatabaseTestResult.TESTEDOK; + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.SCHEMA_INVALID; + } + } else { + testingStatus = DatabaseTestResult.DB_DOES_NOT_EXIST; + } } return testingStatus; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java index de568c7553..01d8ed1d6f 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java @@ -24,7 +24,7 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; */ public interface CentralRepoDbSettings { - public void saveSettings(); + void saveSettings(); boolean createDatabase(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java index 42df359673..27a7b16278 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/DatabaseTestResult.java @@ -18,6 +18,9 @@ */ package org.sleuthkit.autopsy.centralrepository.datamodel; +/** + * provides the status of the database after attempting to validate central repo settings + */ public enum DatabaseTestResult { UNTESTED, CONNECTION_FAILED, diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 8f96140837..bd960af6e9 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -23,7 +23,6 @@ import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import org.openide.modules.ModuleInstall; -import org.openide.util.Exceptions; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; @@ -99,7 +98,7 @@ public class Installer extends ModuleInstall { reportUpgradeError(ex); } }); - } catch (Exception ex) { + } catch (InterruptedException | InvocationTargetException ex) { LOGGER.log(Level.SEVERE, "There was an error while running the swing utility invoke later while creating the central repository database", ex); } } // if no GUI, just initialize @@ -144,7 +143,7 @@ public class Installer extends ModuleInstall { "Installer.centralRepoUpgradeFailed.title"), JOptionPane.ERROR_MESSAGE); }); - } catch (Exception e) { + } catch (InterruptedException | InvocationTargetException e) { LOGGER.warning("There was an error while running the swing utility invoke later while displaying an error " + "for creating the central repository database: " + e.getMessage() + System.lineSeparator() + e.getStackTrace()); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index db657d7fab..373a746cab 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -614,22 +614,15 @@ public class EamDbSettingsDialog extends JDialog { @Messages({"EamDbSettingsDialog.validation.incompleteFields=Fill in all values for the selected database."}) private boolean databaseFieldsArePopulated() { boolean result = true; - switch (manager.getSelectedPlatform()) { - case POSTGRESQL: - result = !tbDbHostname.getText().trim().isEmpty() - && !tbDbPort.getText().trim().isEmpty() - // && !tbDbName.getText().trim().isEmpty() - && !tbDbUsername.getText().trim().isEmpty() - && 0 < jpDbPassword.getPassword().length; - - break; - - case SQLITE: - result = !tfDatabasePath.getText().trim().isEmpty(); - break; + if (manager.getSelectedPlatform() == CentralRepoPlatforms.POSTGRESQL) { + result = !tbDbHostname.getText().trim().isEmpty() + && !tbDbPort.getText().trim().isEmpty() + // && !tbDbName.getText().trim().isEmpty() + && !tbDbUsername.getText().trim().isEmpty() + && 0 < jpDbPassword.getPassword().length; } - - if (!result) { + else if (manager.getSelectedPlatform() == CentralRepoPlatforms.SQLITE) { + result = !tfDatabasePath.getText().trim().isEmpty(); } return result; @@ -688,7 +681,7 @@ public class EamDbSettingsDialog extends JDialog { tfDatabasePath.getText().trim(), new String(jpDbPassword.getPassword())); } - catch (Exception e) { + catch (CentralRepoException | NumberFormatException | IllegalStateException e) { return false; } From 86285c071c659a865743e68655a5ca0eb02e3a8e Mon Sep 17 00:00:00 2001 From: "U-BASIS\\gregd" Date: Mon, 24 Feb 2020 13:37:29 -0500 Subject: [PATCH 23/77] further cleanup of central repo code --- .../datamodel/CentralRepoDbManager.java | 143 +++++++++++------- .../optionspanel/EamDbSettingsDialog.java | 18 +-- 2 files changed, 93 insertions(+), 68 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index a6b0003c35..e4f9eea857 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -34,6 +34,82 @@ public class CentralRepoDbManager { private static final String CENTRAL_REPO_DB_NAME = "central_repository"; + /** + * attains the database connectivity for central repository + * + * @return the CentralRepository object to connect to + * @throws CentralRepoException + */ + private static CentralRepository attainCentralRepository() throws CentralRepoException { + //get connection + try { + return CentralRepository.getInstance(); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); + onUpgradeError("Error updating central repository, unable to make connection", + Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } + + // will never be reached + return null; + } + + /** + * attains central repository lock + * + * @param db the database connection + * @return the lock if acquired + * @throws CentralRepoException + */ + private static CoordinationService.Lock attainCentralRepoLock(CentralRepository db) throws CentralRepoException { + try { + // This may return null if locking isn't supported, which is fine. It will + // throw an exception if locking is supported but we can't get the lock + // (meaning the database is in use by another user) + return db.getExclusiveMultiUserDbLock(); + //perform upgrade + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); + onUpgradeError("Error updating central repository, unable to acquire exclusive lock", + Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } + + // will never be reached + return null; + } + + /** + * updates central repository schema if necessary + * + * @param db the database connectivity + * @param lock the acquired lock + * @throws CentralRepoException + */ + private static void updatedDbSchema(CentralRepository db, CoordinationService.Lock lock) throws CentralRepoException { + try { + db.upgradeSchema(); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository", ex); + onUpgradeError("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } catch (SQLException ex) { + logger.log(Level.SEVERE, "Error updating central repository", ex); + onUpgradeError("Error updating central repository", + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } catch (IncompatibleCentralRepoException ex) { + logger.log(Level.SEVERE, "Error updating central repository", ex); + onUpgradeError("Error updating central repository", + ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); + } finally { + if (lock != null) { + try { + lock.release(); + } catch (CoordinationService.CoordinationServiceException ex) { + logger.log(Level.SEVERE, "Error releasing database lock", ex); + } + } + } + } + /** * Upgrade the current Central Reposity schema to the newest version. If the * upgrade fails, the Central Repository will be disabled and the current @@ -45,60 +121,18 @@ public class CentralRepoDbManager { return; } - CentralRepository db = null; - CoordinationService.Lock lock = null; - - //get connection - try { - db = CentralRepository.getInstance(); - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository, unable to make connection", ex); - onUpgradeError("Error updating central repository, unable to make connection", - Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } + CentralRepository db = attainCentralRepository(); //get lock necessary for upgrade if (db != null) { - try { - // This may return null if locking isn't supported, which is fine. It will - // throw an exception if locking is supported but we can't get the lock - // (meaning the database is in use by another user) - lock = db.getExclusiveMultiUserDbLock(); - //perform upgrade - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository, unable to acquire exclusive lock", ex); - onUpgradeError("Error updating central repository, unable to acquire exclusive lock", - Bundle.EamDbUtil_exclusiveLockAquisitionFailure_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } - - try { - db.upgradeSchema(); - } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository", ex); - onUpgradeError("Error updating central repository", ex.getUserMessage() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } catch (SQLException ex) { - logger.log(Level.SEVERE, "Error updating central repository", ex); - onUpgradeError("Error updating central repository", - Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } catch (IncompatibleCentralRepoException ex) { - logger.log(Level.SEVERE, "Error updating central repository", ex); - onUpgradeError("Error updating central repository", - ex.getMessage() + "\n\n" + Bundle.EamDbUtil_centralRepoUpgradeFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), ex); - } finally { - if (lock != null) { - try { - lock.release(); - } catch (CoordinationService.CoordinationServiceException ex) { - logger.log(Level.SEVERE, "Error releasing database lock", ex); - } - } - } + CoordinationService.Lock lock = attainCentralRepoLock(db); + updatedDbSchema(db, lock); } else { - onUpgradeError("Unable to connect to database", - Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), null); + onUpgradeError("Unable to connect to database", + Bundle.EamDbUtil_centralRepoConnectionFailed_message() + Bundle.EamDbUtil_centralRepoDisabled_message(), null); } } - + private static void onUpgradeError(String message, String desc, Exception innerException) throws CentralRepoException { // Disable the central repo and clear the current settings. try { @@ -111,15 +145,11 @@ public class CentralRepoDbManager { CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.DISABLED.name()); CentralRepoPlatforms.saveSelectedPlatform(); if (innerException == null) { - throw new CentralRepoException(message, desc); - } - else { - throw new CentralRepoException(message, desc, innerException); + throw new CentralRepoException(message, desc); + } else { + throw new CentralRepoException(message, desc, innerException); } } - - - private DatabaseTestResult testingStatus; private CentralRepoPlatforms selectedPlatform; @@ -332,8 +362,7 @@ public class CentralRepoDbManager { } else { testingStatus = DatabaseTestResult.CONNECTION_FAILED; } - } - else if (selectedPlatform == CentralRepoPlatforms.SQLITE) { + } else if (selectedPlatform == CentralRepoPlatforms.SQLITE) { if (dbSettingsSqlite.dbFileExists()) { if (dbSettingsSqlite.verifyConnection()) { if (dbSettingsSqlite.verifyDatabaseSchema()) { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 373a746cab..25289da2af 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -414,17 +414,13 @@ public class EamDbSettingsDialog extends JDialog { setTextPrompts(); setTextBoxListeners(); manager.clearStatus(); - switch (manager.getSelectedPlatform()) { - case SQLITE: - updatePostgresFields(false); - updateSqliteFields(true); - break; - default: - POSTGRESQL: - updatePostgresFields(true); - updateSqliteFields(false); - break; - + if (manager.getSelectedPlatform() == CentralRepoPlatforms.SQLITE) { + updatePostgresFields(false); + updateSqliteFields(true); + } + else { + updatePostgresFields(true); + updateSqliteFields(false); } displayDatabaseSettings(CentralRepoPlatforms.POSTGRESQL.equals(manager.getSelectedPlatform())); } From 7de33d4b35ae2c9c1c307ad293707cdf8447a73e Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Mon, 24 Feb 2020 13:40:09 -0500 Subject: [PATCH 24/77] 6014: Update central repository database creation to make personas tables. --- .../datamodel/CentralRepository.java | 11 +- .../CorrelationAttributeInstance.java | 42 ++- .../centralrepository/datamodel/Persona.java | 87 +++++ .../datamodel/RdbmsCentralRepo.java | 74 ++++ .../datamodel/RdbmsCentralRepoFactory.java | 340 +++++++++++++++++- .../optionspanel/EamDbSettingsDialog.java | 1 - .../CommonAttributeCaseSearchResults.java | 5 +- .../CommonAttributeCountSearchResults.java | 7 +- .../CommonAttributePanel.java | 6 +- .../InterCasePanel.java | 5 +- .../CorrelationCaseChildNodeFactory.java | 4 +- .../InterCaseTestUtils.java | 13 +- 12 files changed, 554 insertions(+), 41 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Persona.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index 3e7ac158a9..e357d529e5 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -802,5 +802,14 @@ public interface CentralRepository { * * @throws CentralRepoException */ - public void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback) throws CentralRepoException; + public void processSelectClause(String selectClause, InstanceTableCallback instanceTableCallback) throws CentralRepoException; + + + /** + * Returns list of all correlation types. + * + * @return list of Correlation types + * @throws CentralRepoException + */ + public List getCorrelationTypes() throws CentralRepoException; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index f13b27787d..a8974f8e5a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2015-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -24,6 +24,7 @@ import java.util.List; import java.util.Objects; import java.util.regex.Pattern; import org.openide.util.NbBundle.Messages; +import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.TskData; /** @@ -220,6 +221,9 @@ public class CorrelationAttributeInstance implements Serializable { public static final int IMEI_TYPE_ID = 7; public static final int IMSI_TYPE_ID = 8; public static final int ICCID_TYPE_ID = 9; + + // An offset to assign Ids for additional correlation types. + public static final int ADDITIONAL_TYPES_BASE_ID = 1000; /** * Load the default correlation types @@ -238,18 +242,30 @@ public class CorrelationAttributeInstance implements Serializable { "CorrelationType.IMSI.displayName=IMSI Number", "CorrelationType.ICCID.displayName=ICCID Number"}) public static List getDefaultCorrelationTypes() throws CentralRepoException { - List DEFAULT_CORRELATION_TYPES = new ArrayList<>(); - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(DOMAIN_TYPE_ID, Bundle.CorrelationType_DOMAIN_displayName(), "domain", true, true)); // NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(SSID_TYPE_ID, Bundle.CorrelationType_SSID_displayName(), "wireless_networks", true, true)); // NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(MAC_TYPE_ID, Bundle.CorrelationType_MAC_displayName(), "mac_address", true, true)); //NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(IMEI_TYPE_ID, Bundle.CorrelationType_IMEI_displayName(), "imei_number", true, true)); //NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(IMSI_TYPE_ID, Bundle.CorrelationType_IMSI_displayName(), "imsi_number", true, true)); //NON-NLS - DEFAULT_CORRELATION_TYPES.add(new CorrelationAttributeInstance.Type(ICCID_TYPE_ID, Bundle.CorrelationType_ICCID_displayName(), "iccid_number", true, true)); //NON-NLS - return DEFAULT_CORRELATION_TYPES; + List defaultCorrelationTypes = new ArrayList<>(); + + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(FILES_TYPE_ID, Bundle.CorrelationType_FILES_displayName(), "file", true, true)); // NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(DOMAIN_TYPE_ID, Bundle.CorrelationType_DOMAIN_displayName(), "domain", true, true)); // NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(EMAIL_TYPE_ID, Bundle.CorrelationType_EMAIL_displayName(), "email_address", true, true)); // NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(PHONE_TYPE_ID, Bundle.CorrelationType_PHONE_displayName(), "phone_number", true, true)); // NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(USBID_TYPE_ID, Bundle.CorrelationType_USBID_displayName(), "usb_devices", true, true)); // NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(SSID_TYPE_ID, Bundle.CorrelationType_SSID_displayName(), "wireless_networks", true, true)); // NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(MAC_TYPE_ID, Bundle.CorrelationType_MAC_displayName(), "mac_address", true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(IMEI_TYPE_ID, Bundle.CorrelationType_IMEI_displayName(), "imei_number", true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(IMSI_TYPE_ID, Bundle.CorrelationType_IMSI_displayName(), "imsi_number", true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(ICCID_TYPE_ID, Bundle.CorrelationType_ICCID_displayName(), "iccid_number", true, true)); //NON-NLS + + // Create Correlation Types for Accounts. + int correlationTypeId = ADDITIONAL_TYPES_BASE_ID; + for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { + // Skip Phone and Email accounts as there are already Correlation types defined for those. + if (type != Account.Type.EMAIL && type != Account.Type.PHONE) { + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(correlationTypeId, type.getDisplayName(), type.getTypeName().toLowerCase(), true, true)); //NON-NLS + correlationTypeId++; + } + } + + return defaultCorrelationTypes; } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Persona.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Persona.java new file mode 100644 index 0000000000..5fc458353b --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/Persona.java @@ -0,0 +1,87 @@ +/* + * Central Repository + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.centralrepository.datamodel; + +/** + * This class abstracts a persona. + * + * An examiner may create a persona from an account. + * + */ +class Persona { + + /** + * Defines level of confidence in assigning a persona to an account. + */ + public enum Confidence { + UNKNOWN(1, "Unknown"), + LOW(2, "Low confidence"), + MEDIUM(3, "Medium confidence"), + HIGH(4, "High confidence"), + DERIVED(5, "Derived directly"); + + private final String name; + private final int level_id; + + Confidence(int level, String name) { + this.name = name; + this.level_id = level; + + } + + @Override + public String toString() { + return name; + } + + public int getLevel() { + return this.level_id; + } + } + + /** + * Defines status of a persona. + */ + public enum PersonaStatus { + + UNKNOWN(1, "Unknown"), + ACTIVE(2, "Active"), + MERGED(3, "Merged"), + SPLIT(4, "Split"), + DELETED(5, "Deleted"); + + private final String description; + private final int status_id; + + PersonaStatus(int status, String description) { + this.status_id = status; + this.description = description; + } + + @Override + public String toString() { + return description; + } + + public int getStatus() { + return this.status_id; + } + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index 513fd3f944..fedf0b75c9 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -1373,6 +1373,9 @@ abstract class RdbmsCentralRepo implements CentralRepository { } synchronized (bulkArtifacts) { + if (bulkArtifacts.get(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())) == null) { + bulkArtifacts.put(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()), new ArrayList<>()); + } bulkArtifacts.get(CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType())).add(eamArtifact); bulkArtifactsCount++; @@ -2845,6 +2848,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { typeId = newCorrelationTypeKnownId(newType); } + typeCache.put(newType.getId(), newType); return typeId; } @@ -3105,6 +3109,45 @@ abstract class RdbmsCentralRepo implements CentralRepository { } } + /** + * Returns a list of all correlation types. It uses the cache to build the + * list. If the cache is empty, it reads from the database and loads up the + * cache. + * + * @return List of correlation types. + * @throws CentralRepoException + */ + @Override + public List getCorrelationTypes() throws CentralRepoException { + + if (typeCache.size() == 0) { + getCorrelationTypesFromCr(); + } + + return new ArrayList<>(typeCache.asMap().values()); + } + + /** + * Gets a Correlation type with the specified name. + * + * @param correlationtypeName Correlation type name + * @return Correlation type matching the given name, null if none matches. + * + * @throws CentralRepoException + */ + public CorrelationAttributeInstance.Type getCorrelationTypeByName(String correlationtypeName) throws CentralRepoException { + List correlationTypesList = getCorrelationTypes(); + + CorrelationAttributeInstance.Type correlationType + = correlationTypesList.stream() + .filter(x -> correlationtypeName.equalsIgnoreCase(x.getDisplayName())) + .findAny() + .orElse(null); + + return null; + } + + /** * Get the EamArtifact.Type that has the given Type.Id from the central repo * @@ -3142,6 +3185,37 @@ abstract class RdbmsCentralRepo implements CentralRepository { } } + /** + * Reads the correlation types from the database and loads them up in the cache. + * + * @throws CentralRepoException If there is an error. + */ + private void getCorrelationTypesFromCr() throws CentralRepoException { + + // clear out the cache + typeCache.invalidateAll(); + + Connection conn = connect(); + PreparedStatement preparedStatement = null; + ResultSet resultSet = null; + + String sql = "SELECT * FROM correlation_types"; + try { + preparedStatement = conn.prepareStatement(sql); + resultSet = preparedStatement.executeQuery(); + while (resultSet.next()) { + CorrelationAttributeInstance.Type aType = getCorrelationTypeFromResultSet(resultSet); + typeCache.put(aType.getId(), aType); + } + } catch (SQLException ex) { + throw new CentralRepoException("Error getting correlation types.", ex); // NON-NLS + } finally { + CentralRepoDbUtil.closeStatement(preparedStatement); + CentralRepoDbUtil.closeResultSet(resultSet); + CentralRepoDbUtil.closeConnection(conn); + } + } + /** * Convert a ResultSet to a EamCase object * diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index 33b6009dea..3ef09b263c 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -19,12 +19,17 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import java.util.logging.Level; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona.Confidence; +import org.sleuthkit.autopsy.centralrepository.datamodel.Persona.PersonaStatus; import static org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepo.SOFTWARE_CR_DB_SCHEMA_VERSION; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.datamodel.Account; /** * Creates the CR schema and populates it with initial data. @@ -132,11 +137,11 @@ public class RdbmsCentralRepoFactory { stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); // Create a separate instance and reference table for each artifact type - List DEFAULT_CORRELATION_TYPES = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + List defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes(); String reference_type_dbname; String instance_type_dbname; - for (CorrelationAttributeInstance.Type type : DEFAULT_CORRELATION_TYPES) { + for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) { reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type); instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type); @@ -154,6 +159,8 @@ public class RdbmsCentralRepoFactory { stmt.execute(String.format(getReferenceTypeValueKnownstatusIndexTemplate(), reference_type_dbname, reference_type_dbname)); } } + + createPersonaTables(stmt); } catch (SQLException ex) { LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS return false; @@ -184,7 +191,11 @@ public class RdbmsCentralRepoFactory { return false; } - boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) && CentralRepoDbUtil.insertDefaultOrganization(conn); + boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) + && CentralRepoDbUtil.insertDefaultOrganization(conn) + && insertDefaultPersonaTablesContent(conn); + + CentralRepoDbUtil.closeConnection(conn); return result; } @@ -413,7 +424,7 @@ public class RdbmsCentralRepoFactory { /** * Get the template for creating an index on the value column of an instance * table. %s will exist in the template where the name of the new table will - * be addedd. + * be added. * * @return a String which is a template for adding an index to the value * column of a _instances table @@ -426,7 +437,7 @@ public class RdbmsCentralRepoFactory { /** * Get the template for creating an index on the known_status column of an * instance table. %s will exist in the template where the name of the new - * table will be addedd. + * table will be added. * * @return a String which is a template for adding an index to the * known_status column of a _instances table @@ -439,7 +450,7 @@ public class RdbmsCentralRepoFactory { /** * Get the template for creating an index on the file_obj_id column of an * instance table. %s will exist in the template where the name of the new - * table will be addedd. + * table will be added. * * @return a String which is a template for adding an index to the * file_obj_id column of a _instances table @@ -525,7 +536,16 @@ public class RdbmsCentralRepoFactory { } } - + private static String getOnConflictDoNothingClause(CentralRepoPlatforms selectedPlatform) { + switch (selectedPlatform) { + case POSTGRESQL: + return "ON CONFLICT DO NOTHING"; + case SQLITE: + return ""; + default: + return ""; + } + } /** * Returns an ephemeral connection to the CR database. * @@ -541,4 +561,310 @@ public class RdbmsCentralRepoFactory { return null; } } + + /** + * Creates the tables for Persona. + * + * @return True if success, False otherwise. + */ + private boolean createPersonaTables(Statement stmt) throws SQLException { + + stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform)); + stmt.execute(getCreateConfidenceTableStatement(selectedPlatform)); + stmt.execute(getCreateExaminersTableStatement(selectedPlatform)); + stmt.execute(getCreatePersonaStatusTableStatement(selectedPlatform)); + stmt.execute(getCreateAliasesTableStatement(selectedPlatform)); + + stmt.execute(getCreateAccountsTableStatement(selectedPlatform)); + stmt.execute(getCreatePersonasTableStatement(selectedPlatform)); + stmt.execute(getCreatePersonaAliasTableStatement(selectedPlatform)); + stmt.execute(getCreatePersonaMetadataTableStatement(selectedPlatform)); + stmt.execute(getCreatePersonaAccountsTableStatement(selectedPlatform)); + + return true; + } + + + /** + * Get the SQL string for creating a new account_types table in a central + * repository. + * + * @return SQL string for creating account_types table + */ + static String getCreateAccountTypesTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS account_types (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "type_name TEXT NOT NULL," + + "display_name TEXT NOT NULL," + + "correlation_type_id " + getBigIntType(selectedPlatform) + " ," + + "CONSTRAINT type_name_unique UNIQUE (type_name)," + + "FOREIGN KEY (correlation_type_id) REFERENCES correlation_types(id)" + + ")"; + } + + /** + * Get the SQL String for creating a new confidence table in a central + * repository. + * + * @return SQL string for creating confidence table + */ + static String getCreateConfidenceTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS confidence (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "confidence_id integer NOT NULL," + + "description TEXT," + + "CONSTRAINT level_unique UNIQUE (confidence_id)" + + ")"; + } + + /** + * Get the SQL String for creating a new examiners table in a central + * repository. + * + * @return SQL string for creating examiners table + */ + static String getCreateExaminersTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS examiners (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "login_name TEXT NOT NULL," + + "display_name TEXT," + + "CONSTRAINT login_name_unique UNIQUE(login_name)" + + ")"; + } + + /** + * Get the SQL String for creating a new persona_status table in a central + * repository. + * + * @return SQL string for creating persona_status table + */ + static String getCreatePersonaStatusTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS persona_status (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "status_id integer NOT NULL," + + "status TEXT NOT NULL," + + "CONSTRAINT status_unique UNIQUE(status_id)" + + ")"; + } + + /** + * Get the SQL String for creating a new aliases table in a central + * repository. + * + * @return SQL string for creating aliases table + */ + static String getCreateAliasesTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS aliases (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "alias TEXT NOT NULL," + + "CONSTRAINT alias_unique UNIQUE(alias)" + + ")"; + } + + /** + * Get the SQL String for creating a new accounts table in a central + * repository. + * + * @return SQL string for creating accounts table + */ + static String getCreateAccountsTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS accounts (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "account_type_id integer NOT NULL," + + "account_unique_identifier TEXT NOT NULL," + + "CONSTRAINT account_unique UNIQUE(account_type_id, account_unique_identifier)," + + "FOREIGN KEY (account_type_id) REFERENCES account_types(id)" + + ")"; + } + + /** + * Get the SQL String for creating a new personas table in a central + * repository. + * + * @return SQL string for creating personas table + */ + static String getCreatePersonasTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS personas (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "uuid TEXT NOT NULL," + + "comment TEXT NOT NULL," + + "name TEXT NOT NULL," + + "created_date " + getBigIntType(selectedPlatform) + " ," + + "modified_date " + getBigIntType(selectedPlatform) + " ," + + "status_id integer NOT NULL," + + "CONSTRAINT uuid_unique UNIQUE(uuid)," + + "FOREIGN KEY (status_id) REFERENCES persona_status(status_id)" + + ")"; + } + + /** + * Get the SQL String for creating a new persona_alias table in a central + * repository. + * + * @return SQL string for creating persona_alias table + */ + static String getCreatePersonaAliasTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS persona_alias (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "persona_id " + getBigIntType(selectedPlatform) + " ," + + "alias_id " + getBigIntType(selectedPlatform) + " ," + + "justification TEXT NOT NULL," + + "confidence_id integer NOT NULL," + + "date_added " + getBigIntType(selectedPlatform) + " ," + + "examiner_id integer NOT NULL," + + "FOREIGN KEY (persona_id) REFERENCES personas(id)," + + "FOREIGN KEY (alias_id) REFERENCES aliases(id)," + + "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," + + "FOREIGN KEY (examiner_id) REFERENCES examiners(id)" + + ")"; + } + + /** + * Get the SQL String for creating a new persona_metadata table in a central + * repository. + * + * @return SQL string for creating persona_metadata table + */ + static String getCreatePersonaMetadataTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS persona_metadata (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "persona_id " + getBigIntType(selectedPlatform) + " ," + + "name TEXT NOT NULL," + + "value TEXT NOT NULL," + + "justification TEXT NOT NULL," + + "confidence_id integer NOT NULL," + + "date_added " + getBigIntType(selectedPlatform) + " ," + + "examiner_id integer NOT NULL," + + "CONSTRAINT unique_metadata UNIQUE(persona_id, name)," + + "FOREIGN KEY (persona_id) REFERENCES personas(id)," + + "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," + + "FOREIGN KEY (examiner_id) REFERENCES examiners(id)" + + ")"; + } + + /** + * Get the SQL String for creating a new persona_accounts table in a central + * repository. + * + * @return SQL string for creating persona_accounts table + */ + static String getCreatePersonaAccountsTableStatement(CentralRepoPlatforms selectedPlatform) { + + return "CREATE TABLE IF NOT EXISTS persona_accounts (" + + getNumericPrimaryKeyClause("id", selectedPlatform) + + "persona_id " + getBigIntType(selectedPlatform) + " ," + + "account_id " + getBigIntType(selectedPlatform) + " ," + + "justification TEXT NOT NULL," + + "confidence_id integer NOT NULL," + + "date_added " + getBigIntType(selectedPlatform) + " ," + + "examiner_id integer NOT NULL," + + "FOREIGN KEY (persona_id) REFERENCES personas(id)," + + "FOREIGN KEY (account_id) REFERENCES accounts(id)," + + "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," + + "FOREIGN KEY (examiner_id) REFERENCES examiners(id)" + + ")"; + } + + + /** + * Inserts the default content in persona related tables. + * + * @param conn Database connection to use. + * + * @return True if success, false otherwise. + */ + private boolean insertDefaultPersonaTablesContent(Connection conn) { + + Statement stmt = null; + try { + stmt = conn.createStatement(); + + // populate the confidence table + for (Confidence confidence : Persona.Confidence.values()) { + String sqlString = "INSERT INTO confidence (confidence_id, description) VALUES ( " + confidence.getLevel() + ", '" + confidence.toString() + "')" //NON-NLS + + getOnConflictDoNothingClause(selectedPlatform); + stmt.execute(sqlString); + } + + // populate the persona_status table + for (PersonaStatus status : Persona.PersonaStatus.values()) { + String sqlString = "INSERT INTO persona_status (status_id, status) VALUES ( " + status.getStatus() + ", '" + status.toString() + "')" //NON-NLS + + getOnConflictDoNothingClause(selectedPlatform); + stmt.execute(sqlString); + } + + // Populate the account_types table + for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { + int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type); + if (correlationTypeId > 0) { + String sqlString = String.format("INSERT INTO account_types (type_name, display_name, correlation_type_id) VALUES ('%s', '%s', %d)" + getOnConflictDoNothingClause(selectedPlatform), + type.getTypeName(), type.getDisplayName(), correlationTypeId); + stmt.execute(sqlString); + } + } + + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in Persona tables."), ex); + return false; + } finally { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException ex2) { + LOGGER.log(Level.SEVERE, "Error closing statement.", ex2); + } + } + } + + return true; + } + + /** + * Returns the correlation type id for the given account type, + * from the correlation_types table. + * + * @param conn Connection to use for database query. + * @param accountType Account type to look for. + * ' + * @return correlation type id. + */ + private int getCorrelationTypeIdForAccountType(Connection conn, Account.Type accountType) { + + int typeId = -1; + if (accountType == Account.Type.EMAIL) { + typeId = CorrelationAttributeInstance.EMAIL_TYPE_ID; + } else if (accountType == Account.Type.PHONE) { + typeId = CorrelationAttributeInstance.PHONE_TYPE_ID; + } else { + ResultSet resultSet = null; + + PreparedStatement preparedStatementQuery = null; + String querySql = "SELECT * FROM correlation_types WHERE display_name=?"; + try { + preparedStatementQuery = conn.prepareStatement(querySql); + preparedStatementQuery.setString(1, accountType.getDisplayName()); + + resultSet = preparedStatementQuery.executeQuery(); + if (resultSet.next()) { + typeId = resultSet.getInt("id"); + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, String.format("Failed to get correlation typeId for account type %s.", accountType.getTypeName()), ex); + } finally { + CentralRepoDbUtil.closeStatement(preparedStatementQuery); + CentralRepoDbUtil.closeResultSet(resultSet); + } + } + + return typeId; + } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java index 5c5ba6072b..519a7b2453 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/optionspanel/EamDbSettingsDialog.java @@ -460,7 +460,6 @@ public class EamDbSettingsDialog extends JDialog { if (!result) { // Remove the incomplete database if (dbCreated) { - // RAMAN TBD: migrate deleteDatabase() to RdbmsCentralRepoFactory dbSettingsPostgres.deleteDatabase(); } diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java index 0f87533504..e096638434 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCaseSearchResults.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -123,8 +123,7 @@ final public class CommonAttributeCaseSearchResults { if (currentCaseDataSourceMap == null) { //there are no results return filteredCaseNameToDataSourcesTree; } - CorrelationAttributeInstance.Type attributeType = CorrelationAttributeInstance - .getDefaultCorrelationTypes() + CorrelationAttributeInstance.Type attributeType = CentralRepository.getInstance().getCorrelationTypes() .stream() .filter(filterType -> filterType.getId() == resultTypeId) .findFirst().get(); diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java index 18e7195f34..85923e53b6 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributeCountSearchResults.java @@ -128,14 +128,13 @@ final public class CommonAttributeCountSearchResults { return; } - CorrelationAttributeInstance.Type attributeType = CorrelationAttributeInstance - .getDefaultCorrelationTypes() + CentralRepository eamDb = CentralRepository.getInstance(); + CorrelationAttributeInstance.Type attributeType = eamDb.getCorrelationTypes() .stream() .filter(filterType -> filterType.getId() == this.resultTypeId) .findFirst().get(); - CentralRepository eamDb = CentralRepository.getInstance(); - + Map> itemsToRemove = new HashMap<>(); //Call countUniqueDataSources once to reduce the number of DB queries needed to get //the frequencyPercentage diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java index f56f9dd9a8..43d834e39d 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/CommonAttributePanel.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -255,7 +255,7 @@ final class CommonAttributePanel extends javax.swing.JDialog implements Observer filterByDocuments = interCasePanel.documentsCheckboxIsSelected(); } if (corType == null) { - corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0); + corType = CentralRepository.getInstance().getCorrelationTypes().get(0); } if (caseId == InterCasePanel.NO_CASE_SELECTED) { builder = new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold); @@ -366,7 +366,7 @@ final class CommonAttributePanel extends javax.swing.JDialog implements Observer filterByDocuments = interCasePanel.documentsCheckboxIsSelected(); } if (corType == null) { - corType = CorrelationAttributeInstance.getDefaultCorrelationTypes().get(0); + corType = CentralRepository.getInstance().getCorrelationTypes().get(0); } if (caseId == InterCasePanel.NO_CASE_SELECTED) { builder = new AllInterCaseCommonAttributeSearcher(filterByMedia, filterByDocuments, corType, percentageThreshold); diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java index 88d60db3be..a2c1c01529 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -31,6 +31,7 @@ import java.util.logging.Level; import javax.swing.ComboBoxModel; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.coreutils.Logger; /** @@ -117,7 +118,7 @@ public final class InterCasePanel extends javax.swing.JPanel { void setupCorrelationTypeFilter() { this.correlationTypeFilters = new HashMap<>(); try { - List types = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + List types = CentralRepository.getInstance().getCorrelationTypes(); for (CorrelationAttributeInstance.Type type : types) { correlationTypeFilters.put(type.getDisplayName(), type); this.correlationTypeComboBox.addItem(type.getDisplayName()); diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java index 5105f1628d..49617c9dfb 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2019 Basis Technology Corp. + * Copyright 2019-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -111,7 +111,7 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory(); - List correcationTypeList = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + List correcationTypeList = CentralRepository.getInstance().getCorrelationTypes(); correcationTypeList.forEach((type) -> { correlationTypeMap.put(type.getId(), type); }); diff --git a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java index 69dcdc71b9..65b47bcb3b 100644 --- a/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java +++ b/Core/test/qa-functional/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCaseTestUtils.java @@ -2,7 +2,7 @@ * * Autopsy Forensic Browser * - * Copyright 2018-2019 Basis Technology Corp. + * Copyright 2018-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -62,6 +62,7 @@ import org.sleuthkit.autopsy.modules.photoreccarver.PhotoRecCarverIngestModuleFa import org.sleuthkit.autopsy.modules.vmextractor.VMExtractorIngestModuleFactory; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.centralrepository.datamodel.RdbmsCentralRepoFactory; /** * Utilities for testing intercase correlation feature. @@ -220,7 +221,7 @@ class InterCaseTestUtils { this.kitchenShink = new IngestJobSettings(InterCaseTestUtils.class.getCanonicalName(), IngestType.ALL_MODULES, kitchenSink); try { - Collection types = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + Collection types = CentralRepository.getInstance().getCorrelationTypes(); //TODO use ids instead of strings FILE_TYPE = types.stream().filter(type -> type.getDisplayName().equals("Files")).findAny().get(); @@ -248,7 +249,7 @@ class InterCaseTestUtils { CentralRepository.getInstance().shutdownConnections(); } FileUtils.deleteDirectory(CENTRAL_REPO_DIRECTORY_PATH.toFile()); - } catch (IOException | CentralRepoExceptionex) { + } catch (IOException | CentralRepoException ex) { Exceptions.printStackTrace(ex); Assert.fail(ex.getMessage()); } @@ -297,8 +298,10 @@ class InterCaseTestUtils { crSettings.createDbDirectory(); } - crSettings.initializeDatabaseSchema(); - crSettings.insertDefaultDatabaseContent(); + RdbmsCentralRepoFactory centralRepoSchemaFactory = new RdbmsCentralRepoFactory(CentralRepoPlatforms.SQLITE, crSettings); + centralRepoSchemaFactory.initializeDatabaseSchema(); + centralRepoSchemaFactory.insertDefaultDatabaseContent(); + crSettings.saveSettings(); CentralRepoPlatforms.setSelectedPlatform(CentralRepoPlatforms.SQLITE.name()); CentralRepoPlatforms.saveSelectedPlatform(); From 29c3cb6c25720abe750f3a323587a0316953116b Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Mon, 24 Feb 2020 14:16:37 -0500 Subject: [PATCH 25/77] Addressed Codacy comment. --- .../autopsy/centralrepository/datamodel/CentralRepository.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index e357d529e5..fe54161762 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -811,5 +811,5 @@ public interface CentralRepository { * @return list of Correlation types * @throws CentralRepoException */ - public List getCorrelationTypes() throws CentralRepoException; + List getCorrelationTypes() throws CentralRepoException; } From c8bf39e715490170196add63610ae8ad7508ff35 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 24 Feb 2020 16:00:31 -0500 Subject: [PATCH 26/77] Skeleton for creating correlation attrs for account artifacts --- .../DataContentViewerOtherCases.java | 4 +- .../datamodel/CorrelationAttributeUtil.java | 115 ++++++++++-------- .../eventlisteners/CaseEventListener.java | 4 +- .../eventlisteners/IngestEventsListener.java | 4 +- .../AnnotationsContentViewer.java | 4 +- .../autopsy/datamodel/GetSCOTask.java | 2 +- 6 files changed, 74 insertions(+), 59 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index a28a013220..027a4ad7df 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2017-2019 Basis Technology Corp. + * Copyright 2017-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -464,7 +464,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // correlate on blackboard artifact attributes if they exist and supported BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node); if (bbArtifact != null && CentralRepository.isEnabled()) { - ret.addAll(CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false)); + ret.addAll(CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact)); } // we can correlate based on the MD5 if it is enabled diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 07eb454ac5..9ac0dddf9e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2020 Basis Technology Corp. + * Copyright 2017-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -48,55 +48,61 @@ public class CorrelationAttributeUtil { } /** - * Static factory method to examine a BlackboardArtifact to determine if it - * has contents that can be used for Correlation. If so, return a - * EamArtifact with a single EamArtifactInstance within. If not, return - * null. + * Examines an artifact and makes zero to many correlation attribute + * instances from its attributes. * - * @param artifact BlackboardArtifact to examine - * @param checkEnabled If true, only create a CorrelationAttribute if it is - * enabled + * IMPORTANT: The correlation attribute instances are NOT added to the + * central repository by this method. * - * @return List of EamArtifacts + * @param artifact An artifact. + * + * @return A list, possibly empty, of correlation attribute instances for + * the artifact. */ - public static List makeInstancesFromBlackboardArtifact(BlackboardArtifact artifact, - boolean checkEnabled) { - List eamArtifacts = new ArrayList<>(); + public static List makeAttrsForArtifact(BlackboardArtifact artifact) { + List correlationAttrs = new ArrayList<>(); try { - BlackboardArtifact artifactForInstance = null; + /* + * If the artifact is an interesting artifact hit, examine the + * interesting artifact, not the hit "meta-artifact." + */ + BlackboardArtifact artToExamine = null; if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifact.getArtifactTypeID()) { - // Get the associated artifactForInstance - BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); - if (attribute != null) { - artifactForInstance = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(attribute.getValueLong()); + BlackboardAttribute assocArtifactAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); + if (assocArtifactAttr != null) { + artToExamine = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(assocArtifactAttr.getValueLong()); } } else { - artifactForInstance = artifact; + artToExamine = artifact; } - if (artifactForInstance != null) { - int artifactTypeID = artifactForInstance.getArtifactTypeID(); + + /* + * + */ + if (artToExamine != null) { + int artifactTypeID = artToExamine.getArtifactTypeID(); if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - BlackboardAttribute setNameAttr = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); - if (setNameAttr != null - && CorrelationAttributeUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID); + BlackboardAttribute setNameAttr = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); + if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) { + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID); } + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { - String value = null; - if (null != artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))) { - value = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)).getValueString(); - } else if (null != artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))) { - value = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)).getValueString(); - } else if (null != artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))) { - value = artifactForInstance.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString(); + if (null != artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))) { + value = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)).getValueString(); + } else if (null != artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))) { + value = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)).getValueString(); + } else if (null != artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))) { + value = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString(); } // Remove all non-numeric symbols to semi-normalize phone numbers, preserving leading "+" character if (value != null) { @@ -108,44 +114,53 @@ public class CorrelationAttributeUtil { // Only add the correlation attribute if the resulting phone number large enough to be of use // (these 3-5 digit numbers can be valid, but are not useful for correlation) if (value.length() > 5) { - CorrelationAttributeInstance inst = makeCorrelationAttributeInstanceUsingTypeValue(artifactForInstance, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value); + CorrelationAttributeInstance inst = makeCorrelationAttributeInstanceUsingTypeValue(artToExamine, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value); if (inst != null) { - eamArtifacts.add(inst); + correlationAttrs.add(inst); } } } + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID); - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID); - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) { - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID); - addCorrelationAttributeToList(eamArtifacts, artifactForInstance, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID); + + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) { + // RJCTODO: Make a correlation attribute by switching on account type } } } catch (CentralRepoException ex) { logger.log(Level.SEVERE, "Error getting defined correlation types.", ex); // NON-NLS - return eamArtifacts; + return correlationAttrs; } catch (TskCoreException ex) { logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS - return null; + return correlationAttrs; } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS - return null; + return correlationAttrs; } - return eamArtifacts; + return correlationAttrs; } /** @@ -166,7 +181,7 @@ public class CorrelationAttributeUtil { * @throws CentralRepoException * @throws TskCoreException */ - private static void addCorrelationAttributeToList(List eamArtifacts, BlackboardArtifact artifact, ATTRIBUTE_TYPE bbAttributeType, int typeId) throws CentralRepoException, TskCoreException { + private static void makeCorrAttrFromArtifactAttr(List eamArtifacts, BlackboardArtifact artifact, ATTRIBUTE_TYPE bbAttributeType, int typeId) throws CentralRepoException, TskCoreException { BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(bbAttributeType)); if (attribute != null) { String value = attribute.getValueString(); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index c5f6ebdbe2..2775d5fe4f 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -297,7 +297,7 @@ final class CaseEventListener implements PropertyChangeListener { return; } - List convertedArtifacts = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, true); + List convertedArtifacts = CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { eamArtifact.setComment(comment); try { @@ -370,7 +370,7 @@ final class CaseEventListener implements PropertyChangeListener { if (!hasTagWithConflictingKnownStatus) { //Get the correlation atttributes that correspond to the current BlackboardArtifactTag if their status should be changed //with the initial set of correlation attributes this should be a single correlation attribute - List convertedArtifacts = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbTag.getArtifact(), true); + List convertedArtifacts = CorrelationAttributeUtil.makeAttrsForArtifact(bbTag.getArtifact()); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus()); } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 803f20b8c4..7ee644cbec 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2019 Basis Technology Corp. + * Copyright 2017-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -456,7 +456,7 @@ public class IngestEventsListener { for (BlackboardArtifact bbArtifact : bbArtifacts) { // eamArtifact will be null OR a EamArtifact containing one EamArtifactInstance. - List convertedArtifacts = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, true); + List convertedArtifacts = CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { try { // Only do something with this artifact if it's unique within the job diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 9116ff9b45..9a320f97b7 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -198,7 +198,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data startSection(html, "Central Repository Comments"); List instancesList = new ArrayList<>(); if (artifact != null) { - instancesList.addAll(CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(artifact, false)); + instancesList.addAll(CorrelationAttributeUtil.makeAttrsForArtifact(artifact)); } try { List artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/GetSCOTask.java b/Core/src/org/sleuthkit/autopsy/datamodel/GetSCOTask.java index 5f6f6f1c72..93d5694762 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/GetSCOTask.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/GetSCOTask.java @@ -97,7 +97,7 @@ class GetSCOTask implements Runnable { logger.log(Level.WARNING, "Unable to get correlation type or value to determine value for O column for artifact", ex); } } else { - List listOfPossibleAttributes = CorrelationAttributeUtil.makeInstancesFromBlackboardArtifact(bbArtifact, false); + List listOfPossibleAttributes = CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact); if (listOfPossibleAttributes.size() > 1) { //Don't display anything if there is more than 1 correlation property for an artifact but let the user know description = Bundle.GetSCOTask_occurrences_multipleProperties(); From b1050b96700190e731dc3eaa23b5bf2503b19a85 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 24 Feb 2020 16:14:16 -0500 Subject: [PATCH 27/77] Skeleton for creating correlation attrs for account artifacts --- .../datamodel/CorrelationAttributeUtil.java | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 9ac0dddf9e..b241495b64 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -77,16 +77,16 @@ public class CorrelationAttributeUtil { } /* - * + * */ if (artToExamine != null) { - int artifactTypeID = artToExamine.getArtifactTypeID(); + int artifactTypeID = artToExamine.getArtifactTypeID(); if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { BlackboardAttribute setNameAttr = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) { makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID); } - + } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() @@ -147,7 +147,7 @@ public class CorrelationAttributeUtil { makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) { - // RJCTODO: Make a correlation attribute by switching on account type + makeAttributeFromAccountArtifact(correlationAttrs, artToExamine); } } } catch (CentralRepoException ex) { @@ -163,6 +163,21 @@ public class CorrelationAttributeUtil { return correlationAttrs; } + /** + * Makes a correlation attribute instance for an account artifact. + * + * IMPORTANT: The correlation attribute instance is NOT added to the central + * repository by this method. + * + * @param acctArtifact An account artifact. + */ + private static CorrelationAttributeInstance makeAttributeFromAccountArtifact(List correlationAttrs, BlackboardArtifact acctArtifact) { + // TODO: Convert TSK_ACCOUNT_TYPE attribute to correlation attribute type + // TODO: Extract TSK_ID as value + // return makeCorrelationAttributeInstanceUsingTypeValue(acctArtifact, null, ""); + return null; + } + /** * Add a CorrelationAttributeInstance of the specified type to the provided * list if the artifactForInstance has an Attribute of the given type with a From 75e55dc7d4e96dd4b329413ba046fb12f05c5e73 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Mon, 24 Feb 2020 16:36:05 -0500 Subject: [PATCH 28/77] Skeleton for creating correlation attrs for account artifacts --- .../datamodel/CorrelationAttributeUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index b241495b64..ab1a381720 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -151,13 +151,13 @@ public class CorrelationAttributeUtil { } } } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error getting defined correlation types.", ex); // NON-NLS + logger.log(Level.SEVERE, "Error getting defined correlation types", ex); // NON-NLS return correlationAttrs; } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting attribute while getting type from BlackboardArtifact.", ex); // NON-NLS + logger.log(Level.SEVERE, "Error getting querying case database for artifact attribute", ex); // NON-NLS return correlationAttrs; } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); // NON-NLS + logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS return correlationAttrs; } return correlationAttrs; From a884fbb6945d2c0a7646bdfb50004e6147020e35 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 25 Feb 2020 14:15:00 -0500 Subject: [PATCH 29/77] Normalize file paths before searching for them Normalize file paths before searching for them. Check files exists and if they do create a associated artifact. --- .../recentactivity/ExtractRegistry.java | 65 ++++++++++++------- .../recentactivity/RecentDocumentsByLnk.java | 22 +++++-- 2 files changed, 56 insertions(+), 31 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 97f4b5f709..75e3a3d5f2 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -1204,8 +1204,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts from adobemru records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1233,7 +1231,6 @@ class ExtractRegistry extends Extract { if (fileName.charAt(0) == '/') { fileName = fileName.substring(1,fileName.length() - 1); fileName = fileName.replaceFirst("/", ":/"); - fileName = FilenameUtils.normalize(fileName, true); } // Check to see if more then 2 tokens, Date may not be populated, will default to 0 if (tokens.length > 2) { @@ -1254,12 +1251,16 @@ class ExtractRegistry extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } line = line.trim(); } - } + } if (!bbartifacts.isEmpty()) { postArtifacts(bbartifacts); } @@ -1268,8 +1269,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the mpmru records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1290,7 +1289,6 @@ class ExtractRegistry extends Extract { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); String fileName = tokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); @@ -1299,8 +1297,11 @@ class ExtractRegistry extends Extract { bba = createAssociatedArtifact(fileName, bba); if (bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } - } line = reader.readLine(); } @@ -1315,8 +1316,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the regripper output * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1337,12 +1336,15 @@ class ExtractRegistry extends Extract { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); String fileName = tokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1357,8 +1359,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the WinRAR output * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1380,12 +1380,15 @@ class ExtractRegistry extends Extract { // Split line on "> " which is the record delimiter between position and file String tokens[] = line.split("> "); String fileName = tokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); } @@ -1401,8 +1404,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the runmru ArcHistory records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1418,12 +1419,15 @@ class ExtractRegistry extends Extract { // Columns are // String fileName = line; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if (bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1437,8 +1441,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the Office Documents 2010 records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1462,13 +1464,16 @@ class ExtractRegistry extends Extract { Long docDate = Long.valueOf(tokens[0]); String fileNameTokens[] = tokens[4].split(" - "); String fileName = fileNameTokens[1]; - fileName = FilenameUtils.normalize(fileName, true); Collection attributes = new ArrayList<>(); attributes.add(new BlackboardAttribute(TSK_PATH, getName(), fileName)); attributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME, getName(), docDate)); BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = reader.readLine(); line = line.trim(); @@ -1481,8 +1486,6 @@ class ExtractRegistry extends Extract { /** * Create recently used artifacts to parse the trustrecords records * - * @param regFileName name of the regripper output file - * * @param regFile registry file the artifact is associated with * * @param reader buffered reader to parse adobemru records @@ -1509,7 +1512,6 @@ class ExtractRegistry extends Extract { String tokens[] = line.split(" : "); fileName = tokens[1]; fileName = fileName.replace("%USERPROFILE%", userProfile); - fileName = FilenameUtils.normalize(fileName, true); // Time in the format of Wed May 31 14:33:03 2017 Z try { String fileUsedTime = tokens[0].replaceAll(" Z",""); @@ -1526,6 +1528,10 @@ class ExtractRegistry extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); + if (bba != null) { + bbartifacts.add(bba); + } } line = line.trim(); } @@ -1535,6 +1541,15 @@ class ExtractRegistry extends Extract { } } + /** + * Create associated artifacts using file name and path and the artifact it associates with + * + * @param filePathName file and path of object being associated with + * + * @param bba blackboard artifact to associate with + * + * @returnv BlackboardArtifact or a null value + */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); String fileName = FilenameUtils.getName(filePathName); @@ -1558,7 +1573,9 @@ class ExtractRegistry extends Extract { } } } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error finding lnk actual file."); //NON-NLS + // only catching the error and displaying the message as the file may not exist on the + // system anymore + logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS } return null; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index a02a77b582..639925026b 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -111,7 +111,7 @@ class RecentDocumentsByLnk extends Extract { } Collection bbattributes = new ArrayList<>(); - String path = FilenameUtils.normalize(lnk.getBestPath(), true); + String path = lnk.getBestPath(); bbattributes.add(new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PATH, NbBundle.getMessage(this.getClass(), "RecentDocumentsByLnk.parentModuleName.noSpace"), @@ -133,16 +133,24 @@ class RecentDocumentsByLnk extends Extract { } } } - - - + postArtifacts(bbartifacts); } + /** + * Create associated artifacts using file name and path and the artifact it associates with + * + * @param filePathName file and path of object being associated with + * + * @param bba blackboard artifact to associate with + * + * @returnv BlackboardArtifact or a null value + */ private BlackboardArtifact createAssociatedArtifact(String filePathName, BlackboardArtifact bba) { org.sleuthkit.autopsy.casemodule.services.FileManager fileManager = currentCase.getServices().getFileManager(); - String fileName = FilenameUtils.getName(filePathName); - String filePath = FilenameUtils.getPath(filePathName); + String normalizePathName = FilenameUtils.normalize(filePathName, true); + String fileName = FilenameUtils.getName(normalizePathName); + String filePath = FilenameUtils.getPath(normalizePathName); List sourceFiles; try { sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS @@ -162,7 +170,7 @@ class RecentDocumentsByLnk extends Extract { } } } catch (TskCoreException ex) { - logger.log(Level.WARNING, "Error finding lnk actual file."); //NON-NLS + logger.log(Level.WARNING, String.format("Error finding actual file %s. file may not exist", filePathName)); //NON-NLS } return null; From b78aa977c2672d9c492d144a22d6c4923ba3fb58 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Tue, 25 Feb 2020 14:46:33 -0500 Subject: [PATCH 30/77] 6014: Create accounts & persona tables - Added an account_id column to X_instances tables. --- .../datamodel/RdbmsCentralRepoFactory.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index 3ef09b263c..f61fb42062 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -136,6 +136,10 @@ public class RdbmsCentralRepoFactory { stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')"); stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); + // Create account_types and accounts tab;es which are referred by X_instances tables + stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform)); + stmt.execute(getCreateAccountsTableStatement(selectedPlatform)); + // Create a separate instance and reference table for each artifact type List defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes(); @@ -364,12 +368,14 @@ public class RdbmsCentralRepoFactory { + getNumericPrimaryKeyClause("id", selectedPlatform) + "case_id integer NOT NULL," + "data_source_id integer NOT NULL," + + "account_id " + getBigIntType(selectedPlatform) + " DEFAULT NULL," + "value text NOT NULL," + "file_path text NOT NULL," + "known_status integer NOT NULL," + "comment text," + "file_obj_id " + getBigIntType(selectedPlatform) + " ," + "CONSTRAINT %s_multi_unique UNIQUE(data_source_id, value, file_path)" + getOnConflictIgnoreClause(selectedPlatform) + "," + + "foreign key (account_id) references accounts(id)," + "foreign key (case_id) references cases(id) ON UPDATE SET NULL ON DELETE SET NULL," + "foreign key (data_source_id) references data_sources(id) ON UPDATE SET NULL ON DELETE SET NULL)"; } @@ -569,13 +575,11 @@ public class RdbmsCentralRepoFactory { */ private boolean createPersonaTables(Statement stmt) throws SQLException { - stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform)); stmt.execute(getCreateConfidenceTableStatement(selectedPlatform)); stmt.execute(getCreateExaminersTableStatement(selectedPlatform)); stmt.execute(getCreatePersonaStatusTableStatement(selectedPlatform)); stmt.execute(getCreateAliasesTableStatement(selectedPlatform)); - stmt.execute(getCreateAccountsTableStatement(selectedPlatform)); stmt.execute(getCreatePersonasTableStatement(selectedPlatform)); stmt.execute(getCreatePersonaAliasTableStatement(selectedPlatform)); stmt.execute(getCreatePersonaMetadataTableStatement(selectedPlatform)); From f75e02b739b0c365c3f4540c9c991ab4df1e6080 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 25 Feb 2020 14:49:16 -0500 Subject: [PATCH 31/77] 6022 fix for summarization of files when no textextractor is found --- .../org/sleuthkit/autopsy/filequery/FileSearch.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index ee5c36c8e3..fbf8356e16 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -291,13 +291,21 @@ class FileSearch { * @return The beginning of text from the specified AbstractFile. */ private static String getFirstLines(AbstractFile file) { - try (Reader reader = TextExtractorFactory.getExtractor(file, null).getReader()) { + TextExtractor extractor; + try { + extractor = TextExtractorFactory.getExtractor(file, null); + } catch (TextExtractorFactory.NoTextExtractorFound ignored) { + //no extractor found, use Strings Extractor + extractor = TextExtractorFactory.getStringsExtractor(file, null); + } + + try (Reader reader = extractor.getReader()) { char[] cbuf = new char[PREVIEW_SIZE]; reader.read(cbuf, 0, PREVIEW_SIZE); return new String(cbuf); } catch (IOException ex) { return Bundle.FileSearch_documentSummary_noBytes(); - } catch (TextExtractorFactory.NoTextExtractorFound | TextExtractor.InitReaderException ex) { + } catch (TextExtractor.InitReaderException ex) { return Bundle.FileSearch_documentSummary_noPreview(); } } From 6d412131b032682e5808c5d04551a0a085cd3280 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 25 Feb 2020 16:12:44 -0500 Subject: [PATCH 32/77] updated messages --- .../datamodel/CentralRepoDbManager.java | 15 +++++++++------ .../datamodel/CentralRepoDbSettings.java | 3 +-- .../eventlisteners/Installer.java | 4 +--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index e4f9eea857..38f9218abc 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -35,12 +35,12 @@ public class CentralRepoDbManager { private static final String CENTRAL_REPO_DB_NAME = "central_repository"; /** - * attains the database connectivity for central repository + * obtains the database connectivity for central repository * * @return the CentralRepository object to connect to * @throws CentralRepoException */ - private static CentralRepository attainCentralRepository() throws CentralRepoException { + private static CentralRepository obtainCentralRepository() throws CentralRepoException { //get connection try { return CentralRepository.getInstance(); @@ -55,13 +55,13 @@ public class CentralRepoDbManager { } /** - * attains central repository lock + * obtains central repository lock * * @param db the database connection * @return the lock if acquired * @throws CentralRepoException */ - private static CoordinationService.Lock attainCentralRepoLock(CentralRepository db) throws CentralRepoException { + private static CoordinationService.Lock obtainCentralRepoLock(CentralRepository db) throws CentralRepoException { try { // This may return null if locking isn't supported, which is fine. It will // throw an exception if locking is supported but we can't get the lock @@ -121,11 +121,11 @@ public class CentralRepoDbManager { return; } - CentralRepository db = attainCentralRepository(); + CentralRepository db = obtainCentralRepository(); //get lock necessary for upgrade if (db != null) { - CoordinationService.Lock lock = attainCentralRepoLock(db); + CoordinationService.Lock lock = obtainCentralRepoLock(db); updatedDbSchema(db, lock); } else { onUpgradeError("Unable to connect to database", @@ -163,6 +163,9 @@ public class CentralRepoDbManager { dbSettingsPostgres = new PostgresCentralRepoSettings(); dbSettingsSqlite = new SqliteCentralRepoSettings(); selectedPlatform = CentralRepoPlatforms.getSelectedPlatform(); + + // set the default selected platform for displaying in the ui of EamDbSettingsDialog + // if selected option is not applicable if (selectedPlatform == null || selectedPlatform.equals(CentralRepoPlatforms.DISABLED)) { selectedPlatform = CentralRepoPlatforms.POSTGRESQL; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java index 01d8ed1d6f..f9bf520654 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbSettings.java @@ -19,8 +19,7 @@ package org.sleuthkit.autopsy.centralrepository.datamodel; /** - * - * @author gregd + * common interface for settings pertaining to the database in central repository */ public interface CentralRepoDbSettings { diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index bd960af6e9..cc3836c8ed 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -144,9 +144,7 @@ public class Installer extends ModuleInstall { JOptionPane.ERROR_MESSAGE); }); } catch (InterruptedException | InvocationTargetException e) { - LOGGER.warning("There was an error while running the swing utility invoke later while displaying an error " + - "for creating the central repository database: " - + e.getMessage() + System.lineSeparator() + e.getStackTrace()); + LOGGER.log(Level.WARNING, e.getMessage(), e); } } From 61cfc91c8708c5e2cab8fb21789a1fb633796daf Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 25 Feb 2020 19:50:43 -0500 Subject: [PATCH 33/77] Partial clean up of CorrelationAttributeUtil.java --- .../AddEditCentralRepoCommentAction.java | 4 +- .../DataContentViewerOtherCases.java | 2 +- .../datamodel/CorrelationAttributeUtil.java | 399 +++++++++++------- .../eventlisteners/CaseEventListener.java | 25 +- .../eventlisteners/IngestEventsListener.java | 2 +- .../AnnotationsContentViewer.java | 2 +- .../datamodel/AbstractAbstractFileNode.java | 2 +- .../datamodel/BlackboardArtifactNode.java | 4 +- .../autopsy/datamodel/GetSCOTask.java | 2 +- 9 files changed, 264 insertions(+), 178 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java index dae8bbe312..5427b7b77a 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java @@ -61,10 +61,10 @@ public final class AddEditCentralRepoCommentAction extends AbstractAction { */ public AddEditCentralRepoCommentAction(AbstractFile file) { fileId = file.getId(); - correlationAttributeInstance = CorrelationAttributeUtil.getInstanceFromContent(file); + correlationAttributeInstance = CorrelationAttributeUtil.getCorrAttrForFile(file); if (correlationAttributeInstance == null) { addToDatabase = true; - correlationAttributeInstance = CorrelationAttributeUtil.makeInstanceFromContent(file); + correlationAttributeInstance = CorrelationAttributeUtil.makeCorrAttrFromFile(file); } if (file.getSize() == 0) { putValue(Action.NAME, Bundle.AddEditCentralRepoCommentAction_menuItemText_addEditCentralRepoCommentEmptyFile()); diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java index 027a4ad7df..881e60236e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/contentviewer/DataContentViewerOtherCases.java @@ -464,7 +464,7 @@ public class DataContentViewerOtherCases extends JPanel implements DataContentVi // correlate on blackboard artifact attributes if they exist and supported BlackboardArtifact bbArtifact = getBlackboardArtifactFromNode(node); if (bbArtifact != null && CentralRepository.isEnabled()) { - ret.addAll(CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact)); + ret.addAll(CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact)); } // we can correlate based on the MD5 if it is enabled diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index ab1a381720..a93354901b 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -30,131 +30,110 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.HashUtility; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; /** - * Utility class for correlation attributes in the central repository + * Utility class for working with correlation attributes in the central + * repository. */ public class CorrelationAttributeUtil { private static final Logger logger = Logger.getLogger(CorrelationAttributeUtil.class.getName()); - @Messages({"EamArtifactUtil.emailaddresses.text=Email Addresses"}) - public static String getEmailAddressAttrString() { - return Bundle.EamArtifactUtil_emailaddresses_text(); + /** + * Gets a string that is expected to be the same string that is stored in + * the correlation_types table in the central repository as the display name + * for the email address correlation attribute type. This string is + * duplicated in the CorrelationAttributeInstance class. + * + * TODO (Jira-6088): We should not have multiple deifnitions of this string. + * + * @return The display name of the email address correlation attribute type. + */ + @Messages({"CorrelationAttributeUtil.emailaddresses.text=Email Addresses"}) + private static String getEmailAddressAttrDisplayName() { + return Bundle.CorrelationAttributeUtil_emailaddresses_text(); } /** - * Examines an artifact and makes zero to many correlation attribute - * instances from its attributes. + * Makes zero to many correlation attribute instances from the attributes of + * an artifact. * * IMPORTANT: The correlation attribute instances are NOT added to the * central repository by this method. * + * TODO (Jira-6088): The methods in this low-level, utility class should + * throw exceptions instead of logging them. The reason for this is that the + * clients of the utility class, not the utility class itself, should be in + * charge of error handling policy, per the Autopsy Coding Standard. Note + * that clients of several of these methods currently cannot determine + * whether receiving a null return value is an error or not, plus null + * checking is easy to forget, while catching exceptions is enforced. + * * @param artifact An artifact. * * @return A list, possibly empty, of correlation attribute instances for * the artifact. */ - public static List makeAttrsForArtifact(BlackboardArtifact artifact) { + public static List makeCorrAttrsFromArtifact(BlackboardArtifact artifact) { List correlationAttrs = new ArrayList<>(); try { - /* - * If the artifact is an interesting artifact hit, examine the - * interesting artifact, not the hit "meta-artifact." - */ - BlackboardArtifact artToExamine = null; - if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifact.getArtifactTypeID()) { - BlackboardAttribute assocArtifactAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); - if (assocArtifactAttr != null) { - artToExamine = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(assocArtifactAttr.getValueLong()); - } - } else { - artToExamine = artifact; - } - - /* - * - */ - if (artToExamine != null) { - int artifactTypeID = artToExamine.getArtifactTypeID(); + BlackboardArtifact sourceArtifact = getCorrAttrSourceArtifact(artifact); + if (sourceArtifact != null) { + int artifactTypeID = sourceArtifact.getArtifactTypeID(); if (artifactTypeID == ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID()) { - BlackboardAttribute setNameAttr = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); - if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrString().equals(setNameAttr.getValueString())) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID); + BlackboardAttribute setNameAttr = sourceArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME)); + if (setNameAttr != null && CorrelationAttributeUtil.getEmailAddressAttrDisplayName().equals(setNameAttr.getValueString())) { + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_KEYWORD, CorrelationAttributeInstance.EMAIL_TYPE_ID); } } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_BOOKMARK.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_COOKIE.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_DOWNLOAD.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_WEB_HISTORY.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DOMAIN, CorrelationAttributeInstance.DOMAIN_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_CONTACT.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_CALLLOG.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_MESSAGE.getTypeID()) { - String value = null; - if (null != artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))) { - value = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)).getValueString(); - } else if (null != artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))) { - value = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)).getValueString(); - } else if (null != artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))) { - value = artToExamine.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString(); - } - // Remove all non-numeric symbols to semi-normalize phone numbers, preserving leading "+" character - if (value != null) { - String newValue = value.replaceAll("\\D", ""); - if (value.startsWith("+")) { - newValue = "+" + newValue; - } - value = newValue; - // Only add the correlation attribute if the resulting phone number large enough to be of use - // (these 3-5 digit numbers can be valid, but are not useful for correlation) - if (value.length() > 5) { - CorrelationAttributeInstance inst = makeCorrelationAttributeInstanceUsingTypeValue(artToExamine, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value); - if (inst != null) { - correlationAttrs.add(inst); - } - } - } + makeCorrAttrFromArtifactPhoneAttr(sourceArtifact); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_ATTACHED.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID); - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DEVICE_ID, CorrelationAttributeInstance.USBID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SSID, CorrelationAttributeInstance.SSID_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WIFI_NETWORK_ADAPTER.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_PAIRING.getTypeID() || artifactTypeID == ARTIFACT_TYPE.TSK_BLUETOOTH_ADAPTER.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MAC_ADDRESS, CorrelationAttributeInstance.MAC_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_DEVICE_INFO.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID); - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMEI, CorrelationAttributeInstance.IMEI_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_SIM_ATTACHED.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_IMSI, CorrelationAttributeInstance.IMSI_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ICCID, CorrelationAttributeInstance.ICCID_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_WEB_FORM_ADDRESS.getTypeID()) { - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID); - makeCorrAttrFromArtifactAttr(correlationAttrs, artToExamine, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, CorrelationAttributeInstance.PHONE_TYPE_ID); + makeCorrAttrFromArtifactAttr(correlationAttrs, sourceArtifact, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, CorrelationAttributeInstance.EMAIL_TYPE_ID); } else if (artifactTypeID == ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) { - makeAttributeFromAccountArtifact(correlationAttrs, artToExamine); + makeCorrAttrFromAcctArtifact(correlationAttrs, sourceArtifact); } } } catch (CentralRepoException ex) { - logger.log(Level.SEVERE, "Error getting defined correlation types", ex); // NON-NLS + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", artifact), ex); // NON-NLS return correlationAttrs; } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting querying case database for artifact attribute", ex); // NON-NLS + logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS return correlationAttrs; } catch (NoCurrentCaseException ex) { logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS @@ -163,73 +142,168 @@ public class CorrelationAttributeUtil { return correlationAttrs; } + /** + * Gets the associated artifact of a "meta-artifact" such as an interesting + * artifact hit artifact. + * + * @param artifact An artifact. + * + * @return The associated artifact if the input artifact is a + * "meta-artifact", otherwise the input artifact. + * + * @throws NoCurrentCaseException If there is no open case. + * @throws TskCoreException If there is an error querying thew case + * database. + */ + private static BlackboardArtifact getCorrAttrSourceArtifact(BlackboardArtifact artifact) throws NoCurrentCaseException, TskCoreException { + BlackboardArtifact sourceArtifact = null; + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() == artifact.getArtifactTypeID()) { + BlackboardAttribute assocArtifactAttr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); + if (assocArtifactAttr != null) { + sourceArtifact = Case.getCurrentCaseThrows().getSleuthkitCase().getBlackboardArtifact(assocArtifactAttr.getValueLong()); + } + } else { + sourceArtifact = artifact; + } + return sourceArtifact; + } + + /** + * Make a correlation attribute instance from a phone number attribute of an + * artifact. + * + * @param artifact An artifact with a phone number attribute. + * + * @return The correlation instance artifact or null, if the phone number is + * not a valid correlation attribute. + * + * @throws TskCoreException If there is an error querying the case + * database. + * @throws CentralRepoException If there is an error querying the central + * repository. + */ + private static CorrelationAttributeInstance makeCorrAttrFromArtifactPhoneAttr(BlackboardArtifact artifact) throws TskCoreException, CentralRepoException { + CorrelationAttributeInstance corrAttr = null; + + /* + * Extract the phone number from the artifact attribute. + */ + String value = null; + if (null != artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER))) { + value = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER)).getValueString(); + } else if (null != artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM))) { + value = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM)).getValueString(); + } else if (null != artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO))) { + value = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO)).getValueString(); + } + + /* + * Normalize the phone number. + */ + if (value != null) { + String newValue = value.replaceAll("\\D", ""); + if (value.startsWith("+")) { + newValue = "+" + newValue; + } + value = newValue; + + /* + * Validate the phone number. Three to five digit phone numbers may + * be valid, but they are too short to use as correlation + * attributes. + */ + if (value.length() > 5) { + corrAttr = makeCorrAttr(artifact, CentralRepository.getInstance().getCorrelationTypeById(CorrelationAttributeInstance.PHONE_TYPE_ID), value); + } + } + + return corrAttr; + } + /** * Makes a correlation attribute instance for an account artifact. * * IMPORTANT: The correlation attribute instance is NOT added to the central * repository by this method. * - * @param acctArtifact An account artifact. + * TODO (Jira-6088): The methods in this low-level, utility class should + * throw exceptions instead of logging them. The reason for this is that the + * clients of the utility class, not the utility class itself, should be in + * charge of error handling policy, per the Autopsy Coding Standard. Note + * that clients of several of these methods currently cannot determine + * whether receiving a null return value is an error or not, plus null + * checking is easy to forget, while catching exceptions is enforced. + * + * @param corrAttrInstances A list of correlation attribute instances. + * @param acctArtifact An account artifact. + * + * @return The correlation attribute instance. */ - private static CorrelationAttributeInstance makeAttributeFromAccountArtifact(List correlationAttrs, BlackboardArtifact acctArtifact) { - // TODO: Convert TSK_ACCOUNT_TYPE attribute to correlation attribute type - // TODO: Extract TSK_ID as value - // return makeCorrelationAttributeInstanceUsingTypeValue(acctArtifact, null, ""); - return null; + private static void makeCorrAttrFromAcctArtifact(List corrAttrInstances, BlackboardArtifact acctArtifact) { + // RAMAN TODO: Convert TSK_ACCOUNT_TYPE attribute to correlation attribute type + // RAMAN TODO: Extract TSK_ID as value +// CorrelationAttributeInstance corrAttr = makeCorrAttr(acctArtifact, corrType, corrAttrValue); +// if (corrAttr != null) { +// corrAttrInstances.add(corrAttr); +// } } /** - * Add a CorrelationAttributeInstance of the specified type to the provided - * list if the artifactForInstance has an Attribute of the given type with a - * non empty value. + * Makes a correlation attribute instance from a specified attribute of an + * artifact. The correlation attribute instance is added to an input list. * - * @param eamArtifacts the list of CorrelationAttributeInstance objects - * which should be added to - * @param artifact the blackboard artifactForInstance which we are - * creating a CorrelationAttributeInstance for - * @param bbAttributeType the type of BlackboardAttribute we expect to exist - * for a CorrelationAttributeInstance of this type - * generated from this Blackboard Artifact - * @param typeId the integer type id of the - * CorrelationAttributeInstance type + * @param corrAttrInstances A list of correlation attribute instances. + * @param artifact An artifact. + * @param artAttrType The type of the atrribute of the artifact that + * is to be made into a correlatin attribute + * instance. + * @param typeId The type ID for the desired correlation + * attribute instance. * - * @throws CentralRepoException - * @throws TskCoreException + * @throws CentralRepoException If there is an error querying the central + * repository. + * @throws TskCoreException If there is an error querying the case + * database. */ - private static void makeCorrAttrFromArtifactAttr(List eamArtifacts, BlackboardArtifact artifact, ATTRIBUTE_TYPE bbAttributeType, int typeId) throws CentralRepoException, TskCoreException { - BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(bbAttributeType)); + private static void makeCorrAttrFromArtifactAttr(List corrAttrInstances, BlackboardArtifact artifact, ATTRIBUTE_TYPE artAttrType, int typeId) throws CentralRepoException, TskCoreException { + BlackboardAttribute attribute = artifact.getAttribute(new BlackboardAttribute.Type(artAttrType)); if (attribute != null) { String value = attribute.getValueString(); if ((null != value) && (value.isEmpty() == false)) { - CorrelationAttributeInstance inst = makeCorrelationAttributeInstanceUsingTypeValue(artifact, CentralRepository.getInstance().getCorrelationTypeById(typeId), value); + CorrelationAttributeInstance inst = makeCorrAttr(artifact, CentralRepository.getInstance().getCorrelationTypeById(typeId), value); if (inst != null) { - eamArtifacts.add(inst); + corrAttrInstances.add(inst); } } } } /** - * Uses the determined type and vallue, then looks up instance details to - * create proper CorrelationAttributeInstance. + * Makes a correlation attribute instance of a given type from an artifact. * - * @param bbArtifact the blackboard artifactForInstance - * @param correlationType the given type - * @param value the artifactForInstance value + * @param artifact The artifact. + * @param correlationType the correlation attribute type. + * @param value The correlation attribute value. * - * @return CorrelationAttributeInstance from details, or null if validation - * failed or another error occurred + * TODO (Jira-6088): The methods in this low-level, utility class should + * throw exceptions instead of logging them. The reason for this is that the + * clients of the utility class, not the utility class itself, should be in + * charge of error handling policy, per the Autopsy Coding Standard. Note + * that clients of several of these methods currently cannot determine + * whether receiving a null return value is an error or not, plus null + * checking is easy to forget, while catching exceptions is enforced. + * + * @return The correlation attribute instance or null, if an error occurred. */ - private static CorrelationAttributeInstance makeCorrelationAttributeInstanceUsingTypeValue(BlackboardArtifact bbArtifact, CorrelationAttributeInstance.Type correlationType, String value) { + private static CorrelationAttributeInstance makeCorrAttr(BlackboardArtifact artifact, CorrelationAttributeInstance.Type correlationType, String value) { try { Case currentCase = Case.getCurrentCaseThrows(); - AbstractFile bbSourceFile = currentCase.getSleuthkitCase().getAbstractFileById(bbArtifact.getObjectID()); + AbstractFile bbSourceFile = currentCase.getSleuthkitCase().getAbstractFileById(artifact.getObjectID()); if (null == bbSourceFile) { logger.log(Level.SEVERE, "Error creating artifact instance. Abstract File was null."); // NON-NLS return null; } - // make an instance for the BB source file CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); return new CorrelationAttributeInstance( correlationType, @@ -242,31 +316,34 @@ public class CorrelationAttributeUtil { bbSourceFile.getId()); } catch (TskCoreException ex) { - logger.log(Level.SEVERE, "Error getting AbstractFile for artifact: " + bbArtifact.toString(), ex); // NON-NLS + logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", artifact), ex); // NON-NLS return null; } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { - logger.log(Level.WARNING, "Error creating artifact instance for artifact: " + bbArtifact.toString(), ex); // NON-NLS + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", artifact), ex); // NON-NLS return null; } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Case is closed.", ex); // NON-NLS + logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS return null; } } /** - * Retrieve CorrelationAttribute from the given Content. + * Gets the correlation attribute instance for a file. * - * @param content The content object + * @param file The file. * - * @return The new CorrelationAttribute, or null if retrieval failed. + * TODO (Jira-6088): The methods in this low-level, utility class should + * throw exceptions instead of logging them. The reason for this is that the + * clients of the utility class, not the utility class itself, should be in + * charge of error handling policy, per the Autopsy Coding Standard. Note + * that clients of several of these methods currently cannot determine + * whether receiving a null return value is an error or not, plus null + * checking is easy to forget, while catching exceptions is enforced. + * + * @return The correlation attribute instance or null, if no such + * correlation attribute instance was found or an error occurred. */ - public static CorrelationAttributeInstance getInstanceFromContent(Content content) { - - if (!(content instanceof AbstractFile)) { - return null; - } - - final AbstractFile file = (AbstractFile) content; + public static CorrelationAttributeInstance getCorrAttrForFile(AbstractFile file) { if (!isSupportedAbstractFileType(file)) { return null; @@ -284,11 +361,14 @@ public class CorrelationAttributeUtil { return null; } correlationDataSource = CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource()); - } catch (TskCoreException | CentralRepoException ex) { - logger.log(Level.SEVERE, "Error retrieving correlation attribute.", ex); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error getting querying case database (%s)", file), ex); // NON-NLS + return null; + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS return null; } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Case is closed.", ex); + logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS return null; } @@ -296,20 +376,22 @@ public class CorrelationAttributeUtil { try { correlationAttributeInstance = CentralRepository.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, file.getId()); } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { - logger.log(Level.WARNING, String.format( - "Correlation attribute could not be retrieved for '%s' (id=%d): ", - content.getName(), content.getId()), ex); + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS return null; } - //if there was no correlation attribute found for the item using object_id then check for attributes added with schema 1,1 which lack object_id + + /* + * If no correlation attribute instance was found when querying by file + * object ID, try searching by file path instead. This is necessary + * because file object IDs were not stored in the central repository in + * early versions of its schema. + */ if (correlationAttributeInstance == null && file.getMd5Hash() != null) { String filePath = (file.getParentPath() + file.getName()).toLowerCase(); try { correlationAttributeInstance = CentralRepository.getInstance().getCorrelationAttributeInstance(type, correlationCase, correlationDataSource, file.getMd5Hash(), filePath); } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { - logger.log(Level.WARNING, String.format( - "Correlation attribute could not be retrieved for '%s' (id=%d): ", - content.getName(), content.getId()), ex); + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS return null; } } @@ -318,32 +400,31 @@ public class CorrelationAttributeUtil { } /** - * Create an EamArtifact from the given Content. Will return null if an - * artifactForInstance can not be created - this is not necessarily an error - * case, it just means an artifactForInstance can't be made. If creation - * fails due to an error (and not that the file is the wrong type or it has - * no hash), the error will be logged before returning. + * Makes a correlation attribute instance for a file. * - * Does not add the artifactForInstance to the database. + * IMPORTANT: The correlation attribute instance is NOT added to the central + * repository by this method. * - * @param content The content object + * TODO (Jira-6088): The methods in this low-level, utility class should + * throw exceptions instead of logging them. The reason for this is that the + * clients of the utility class, not the utility class itself, should be in + * charge of error handling policy, per the Autopsy Coding Standard. Note + * that clients of several of these methods currently cannot determine + * whether receiving a null return value is an error or not, plus null + * checking is easy to forget, while catching exceptions is enforced. * - * @return The new EamArtifact or null if creation failed + * @param file The file. + * + * @return The correlation attribute instance or null, if an error occurred. */ - public static CorrelationAttributeInstance makeInstanceFromContent(Content content) { + public static CorrelationAttributeInstance makeCorrAttrFromFile(AbstractFile file) { - if (!(content instanceof AbstractFile)) { + if (!isSupportedAbstractFileType(file)) { return null; } - final AbstractFile af = (AbstractFile) content; - - if (!isSupportedAbstractFileType(af)) { - return null; - } - - // We need a hash to make the artifactForInstance - String md5 = af.getMd5Hash(); + // We need a hash to make the correlation artifact instance. + String md5 = file.getMd5Hash(); if (md5 == null || md5.isEmpty() || HashUtility.isNoDataMd5(md5)) { return null; } @@ -354,31 +435,33 @@ public class CorrelationAttributeUtil { CorrelationCase correlationCase = CentralRepository.getInstance().getCase(Case.getCurrentCaseThrows()); return new CorrelationAttributeInstance( filesType, - af.getMd5Hash(), + file.getMd5Hash(), correlationCase, - CorrelationDataSource.fromTSKDataSource(correlationCase, af.getDataSource()), - af.getParentPath() + af.getName(), + CorrelationDataSource.fromTSKDataSource(correlationCase, file.getDataSource()), + file.getParentPath() + file.getName(), "", TskData.FileKnown.UNKNOWN, - af.getId()); + file.getId()); - } catch (TskCoreException | CentralRepoException | CorrelationAttributeNormalizationException ex) { - logger.log(Level.SEVERE, "Error making correlation attribute.", ex); + } catch (TskCoreException ex) { + logger.log(Level.SEVERE, String.format("Error querying case database (%s)", file), ex); // NON-NLS + return null; + } catch (CentralRepoException | CorrelationAttributeNormalizationException ex) { + logger.log(Level.SEVERE, String.format("Error querying central repository (%s)", file), ex); // NON-NLS return null; } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Case is closed.", ex); + logger.log(Level.SEVERE, "Error getting current case", ex); // NON-NLS return null; } } /** - * Check whether the given abstract file should be processed for the central - * repository. + * Checks whether or not a file is of a type that can be added to the + * central repository as a correlation attribute instance. * - * @param file The file to test + * @param file A file. * - * @return true if the file should be added to the central repo, false - * otherwise + * @return True or false. */ public static boolean isSupportedAbstractFileType(AbstractFile file) { if (file == null) { @@ -405,9 +488,9 @@ public class CorrelationAttributeUtil { } /** - * Constructs a new EamArtifactUtil + * Prevent instantiation of this utility class. */ private CorrelationAttributeUtil() { - //empty constructor } + } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 2775d5fe4f..26c5271d76 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -197,7 +197,7 @@ final class CaseEventListener implements PropertyChangeListener { } } - final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeInstanceFromContent(af); + final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeCorrAttrFromFile(af); if (eamArtifact != null) { // send update to Central Repository db @@ -297,7 +297,7 @@ final class CaseEventListener implements PropertyChangeListener { return; } - List convertedArtifacts = CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact); + List convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { eamArtifact.setComment(comment); try { @@ -370,7 +370,7 @@ final class CaseEventListener implements PropertyChangeListener { if (!hasTagWithConflictingKnownStatus) { //Get the correlation atttributes that correspond to the current BlackboardArtifactTag if their status should be changed //with the initial set of correlation attributes this should be a single correlation attribute - List convertedArtifacts = CorrelationAttributeUtil.makeAttrsForArtifact(bbTag.getArtifact()); + List convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbTag.getArtifact()); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus()); } @@ -406,9 +406,12 @@ final class CaseEventListener implements PropertyChangeListener { } //if the file will have no tags with a status which would prevent the current status from being changed if (!hasTagWithConflictingKnownStatus) { - final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeInstanceFromContent(contentTag.getContent()); - if (eamArtifact != null) { - CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus()); + Content taggedContent = contentTag.getContent(); + if (taggedContent instanceof AbstractFile) { + final CorrelationAttributeInstance eamArtifact = CorrelationAttributeUtil.makeCorrAttrFromFile((AbstractFile)taggedContent); + if (eamArtifact != null) { + CentralRepository.getInstance().setAttributeInstanceKnownStatus(eamArtifact, tagName.getKnownStatus()); + } } } } @@ -455,7 +458,7 @@ final class CaseEventListener implements PropertyChangeListener { } } catch (CentralRepoException ex) { LOGGER.log(Level.SEVERE, "Error adding new data source to the central repository", ex); //NON-NLS - } + } } // DATA_SOURCE_ADDED } @@ -495,7 +498,7 @@ final class CaseEventListener implements PropertyChangeListener { } } // CURRENT_CASE } - + private final class DataSourceNameChangedTask implements Runnable { private final CentralRepository dbManager; @@ -508,12 +511,12 @@ final class CaseEventListener implements PropertyChangeListener { @Override public void run() { - + final DataSourceNameChangedEvent dataSourceNameChangedEvent = (DataSourceNameChangedEvent) event; Content dataSource = dataSourceNameChangedEvent.getDataSource(); String newName = (String) event.getNewValue(); - - if (! StringUtils.isEmpty(newName)) { + + if (!StringUtils.isEmpty(newName)) { if (!CentralRepository.isEnabled()) { return; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java index 7ee644cbec..e79f339c70 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/IngestEventsListener.java @@ -456,7 +456,7 @@ public class IngestEventsListener { for (BlackboardArtifact bbArtifact : bbArtifacts) { // eamArtifact will be null OR a EamArtifact containing one EamArtifactInstance. - List convertedArtifacts = CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact); + List convertedArtifacts = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact); for (CorrelationAttributeInstance eamArtifact : convertedArtifacts) { try { // Only do something with this artifact if it's unique within the job diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java index 9a320f97b7..3c967db3fd 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/AnnotationsContentViewer.java @@ -198,7 +198,7 @@ public class AnnotationsContentViewer extends javax.swing.JPanel implements Data startSection(html, "Central Repository Comments"); List instancesList = new ArrayList<>(); if (artifact != null) { - instancesList.addAll(CorrelationAttributeUtil.makeAttrsForArtifact(artifact)); + instancesList.addAll(CorrelationAttributeUtil.makeCorrAttrsFromArtifact(artifact)); } try { List artifactTypes = CentralRepository.getInstance().getDefinedCorrelationTypes(); diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 9bb2f8c358..441c5c6958 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -549,7 +549,7 @@ public abstract class AbstractAbstractFileNode extends A protected CorrelationAttributeInstance getCorrelationAttributeInstance() { CorrelationAttributeInstance attribute = null; if (CentralRepository.isEnabled() && !UserPreferences.getHideSCOColumns()) { - attribute = CorrelationAttributeUtil.getInstanceFromContent(content); + attribute = CorrelationAttributeUtil.getCorrAttrForFile(content); } return attribute; } diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 7c2b8c92ad..099d91449f 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -605,8 +605,8 @@ public class BlackboardArtifactNode extends AbstractContentNode listOfPossibleAttributes = CorrelationAttributeUtil.makeAttrsForArtifact(bbArtifact); + List listOfPossibleAttributes = CorrelationAttributeUtil.makeCorrAttrsFromArtifact(bbArtifact); if (listOfPossibleAttributes.size() > 1) { //Don't display anything if there is more than 1 correlation property for an artifact but let the user know description = Bundle.GetSCOTask_occurrences_multipleProperties(); From 97a838653178f76167749a88aaac6dc4bdc49880 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Tue, 25 Feb 2020 20:04:30 -0500 Subject: [PATCH 34/77] Partial clean up of CorrelationAttributeUtil.java --- .../centralrepository/AddEditCentralRepoCommentAction.java | 2 +- .../centralrepository/datamodel/CorrelationAttributeUtil.java | 2 +- .../centralrepository/eventlisteners/CaseEventListener.java | 3 +-- .../sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java | 2 +- .../sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java index 5427b7b77a..5f47487f94 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/AddEditCentralRepoCommentAction.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2018 Basis Technology Corp. + * Copyright 2018-2020 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/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index a93354901b..814169ef85 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -169,7 +169,7 @@ public class CorrelationAttributeUtil { } /** - * Make a correlation attribute instance from a phone number attribute of an + * Makes a correlation attribute instance from a phone number attribute of an * artifact. * * @param artifact An artifact with a phone number attribute. diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java index 26c5271d76..1df0e10dc6 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/CaseEventListener.java @@ -1,7 +1,7 @@ /* * Central Repository * - * Copyright 2015-2018 Basis Technology Corp. + * Copyright 2017-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -52,7 +52,6 @@ import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.TagName; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.TskData; -import org.sleuthkit.datamodel.TskDataException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; /** diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java index 441c5c6958..a60964aa19 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/AbstractAbstractFileNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2012-2020 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/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index 099d91449f..b58bb915d0 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -1,7 +1,7 @@ /* * Autopsy Forensic Browser * - * Copyright 2011-2020 Basis Technology Corp. + * Copyright 2012-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); From ff0be451bfc8461690a8c2bc33896c6ab951d4e8 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 25 Feb 2020 21:49:27 -0500 Subject: [PATCH 35/77] Update ExtractRegistry.java Remove null byte in filename before trying to normalize otherwise it will cause an exception --- .../org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java | 1 + 1 file changed, 1 insertion(+) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 75e3a3d5f2..0b119e00d0 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -1251,6 +1251,7 @@ class ExtractRegistry extends Extract { BlackboardArtifact bba = createArtifactWithAttributes(ARTIFACT_TYPE.TSK_RECENT_OBJECT, regFile, attributes); if(bba != null) { bbartifacts.add(bba); + fileName = fileName.replace("\0", ""); bba = createAssociatedArtifact(FilenameUtils.normalize(fileName, true), bba); if (bba != null) { bbartifacts.add(bba); From 2189c18545fa0a887e98a1cf9e1a1c85dff2f02b Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Tue, 25 Feb 2020 22:38:57 -0500 Subject: [PATCH 36/77] Update RecentDocumentsByLnk.java Remove if that is not needed and make codacy happier --- .../recentactivity/RecentDocumentsByLnk.java | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index 639925026b..42e5d2ecb0 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -154,18 +154,16 @@ class RecentDocumentsByLnk extends Extract { List sourceFiles; try { sourceFiles = fileManager.findFiles(dataSource, fileName, filePath); //NON-NLS - if (!sourceFiles.isEmpty()) { - for (AbstractFile sourceFile : sourceFiles) { - if (sourceFile.getParentPath().endsWith(filePath)) { - Collection bbattributes2 = new ArrayList<>(); - bbattributes2.addAll(Arrays.asList( - new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), - bba.getArtifactID()))); + for (AbstractFile sourceFile : sourceFiles) { + if (sourceFile.getParentPath().endsWith(filePath)) { + Collection bbattributes2 = new ArrayList<>(); + bbattributes2.addAll(Arrays.asList( + new BlackboardAttribute(TSK_ASSOCIATED_ARTIFACT, this.getName(), + bba.getArtifactID()))); - BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); - if (associatedObjectBba != null) { - return associatedObjectBba; - } + BlackboardArtifact associatedObjectBba = createArtifactWithAttributes(TSK_ASSOCIATED_OBJECT, sourceFile, bbattributes2); + if (associatedObjectBba != null) { + return associatedObjectBba; } } } From 0c42694ec9830e7c1819083325d5cbcf66fd709d Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 26 Feb 2020 10:11:56 -0500 Subject: [PATCH 37/77] Added suppress deprecation warning to GeoFilterPanel --- Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java index e1c4e0773e..cca9382e51 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/GeoFilterPanel.java @@ -52,6 +52,7 @@ class GeoFilterPanel extends javax.swing.JPanel { private final CheckBoxListPanel checkboxPanel; // Make sure to update if + @SuppressWarnings("deprecation") private static final BlackboardArtifact.ARTIFACT_TYPE[] GPS_ARTIFACT_TYPES = { BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK, BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION, From 50789bceac9ef572f739e4c3a6d45a117d5af0a1 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 26 Feb 2020 10:30:29 -0500 Subject: [PATCH 38/77] Updated properties files --- .../sleuthkit/autopsy/geolocation/Bundle.properties-MERGED | 2 ++ .../sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED index 8e7439fb2f..e5bf351edb 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/geolocation/Bundle.properties-MERGED @@ -30,6 +30,8 @@ GeoTopComponent_no_waypoints_returned_mgs=Applied filter failed to find waypoint GeoTopComponent_no_waypoints_returned_Title=No Waypoints Found GLTopComponent_initilzation_error=An error occurred during waypoint initilization. Geolocation data maybe incomplete. GLTopComponent_name=Geolocation +GLTopComponent_No_dataSource_message=There are no data sources with Geolocation artifacts found. +GLTopComponent_No_dataSource_Title=No Geolocation artifacts found HidingPane_default_title=Filters MapPanel_connection_failure_message=Failed to connect to new geolocation map tile source. MapPanel_connection_failure_message_title=Connection Failure diff --git a/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED index 23f2a02775..bf61ad9be0 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/drones/Bundle.properties-MERGED @@ -1,6 +1,6 @@ DATExtractor_process_message=Processing DJI DAT file: %s DATFileExtractor_Extractor_Name=DAT File Extractor -DroneIngestModule_Description=Description -DroneIngestModule_Name=Drone +DroneIngestModule_Description=Analyzes files generated by drones. +DroneIngestModule_Name=Drone Analyzer # {0} - AbstractFileName DroneIngestModule_process_start=Started {0} From 4cda428708eae34074818dfd6cd15cc6db0d3258 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Wed, 26 Feb 2020 12:25:08 -0500 Subject: [PATCH 39/77] updates in central repository to avoid bug on initialization if sqlite db already exists --- .../datamodel/CentralRepoDbManager.java | 23 ++++++++++++++++++- .../eventlisteners/Installer.java | 16 ++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java index 38f9218abc..d2647965a5 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoDbManager.java @@ -179,9 +179,30 @@ public class CentralRepoDbManager { return dbSettingsSqlite; } - public void setupDefaultSqliteSettings() { + /** + * setup sqlite db with default settings + * @throws CentralRepoException if unable to successfully set up database + */ + public void setupDefaultSqliteDb() throws CentralRepoException { + // change in-memory settings to default sqlite selectedPlatform = CentralRepoPlatforms.SQLITE; dbSettingsSqlite.setupDefaultSettings(); + + // if db is not present, attempt to create it + DatabaseTestResult curStatus = testStatus(); + if (curStatus == DatabaseTestResult.DB_DOES_NOT_EXIST) { + createDb(); + curStatus = testStatus(); + } + + // the only successful setup status is tested ok + if (curStatus != DatabaseTestResult.TESTEDOK) { + throw new CentralRepoException("Unable to successfully create sqlite database"); + } + + // if successfully got here, then save the settings + CentralRepoDbUtil.setUseCentralRepo(true); + saveNewCentralRepo(); } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index cc3836c8ed..1609047e6d 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -29,6 +29,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil; +import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; @@ -57,7 +58,6 @@ public class Installer extends ModuleInstall { } @NbBundle.Messages({ - "Installer.centralRepoUpgradeFailed.title=Central repository disabled", "Installer.initialCreateSqlite.title=Enable Central Repository?", "Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to?", "Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. " + @@ -127,21 +127,19 @@ public class Installer extends ModuleInstall { } private void setupDefaultSqlite() throws CentralRepoException { - CentralRepoDbUtil.setUseCentralRepo(true); CentralRepoDbManager manager = new CentralRepoDbManager(); - manager.setupDefaultSqliteSettings(); - manager.createDb(); - manager.saveNewCentralRepo(); + manager.setupDefaultSqliteDb(); } + @NbBundle.Messages({ "Installer.centralRepoUpgradeFailed.title=Central repository disabled" }) private void reportUpgradeError(CentralRepoException ex) { try { SwingUtilities.invokeAndWait(() -> { JOptionPane.showMessageDialog(null, - ex.getUserMessage(), - NbBundle.getMessage(this.getClass(), - "Installer.centralRepoUpgradeFailed.title"), - JOptionPane.ERROR_MESSAGE); + ex.getUserMessage(), + NbBundle.getMessage(this.getClass(), + "Installer.centralRepoUpgradeFailed.title"), + JOptionPane.ERROR_MESSAGE); }); } catch (InterruptedException | InvocationTargetException e) { LOGGER.log(Level.WARNING, e.getMessage(), e); From 088cfaae6a79d7c9e381877d46cc91ba1a348bce Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 26 Feb 2020 13:02:23 -0500 Subject: [PATCH 40/77] Addressed review comments and Codacy comments. --- .../datamodel/RdbmsCentralRepo.java | 17 +- .../datamodel/RdbmsCentralRepoFactory.java | 191 +++++++++--------- 2 files changed, 96 insertions(+), 112 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index fedf0b75c9..abbae1c867 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -3194,26 +3194,19 @@ abstract class RdbmsCentralRepo implements CentralRepository { // clear out the cache typeCache.invalidateAll(); - - Connection conn = connect(); - PreparedStatement preparedStatement = null; - ResultSet resultSet = null; String sql = "SELECT * FROM correlation_types"; - try { - preparedStatement = conn.prepareStatement(sql); - resultSet = preparedStatement.executeQuery(); + try ( Connection conn = connect(); + PreparedStatement preparedStatement = conn.prepareStatement(sql); + ResultSet resultSet = preparedStatement.executeQuery();) { + while (resultSet.next()) { CorrelationAttributeInstance.Type aType = getCorrelationTypeFromResultSet(resultSet); typeCache.put(aType.getId(), aType); } } catch (SQLException ex) { throw new CentralRepoException("Error getting correlation types.", ex); // NON-NLS - } finally { - CentralRepoDbUtil.closeStatement(preparedStatement); - CentralRepoDbUtil.closeResultSet(resultSet); - CentralRepoDbUtil.closeConnection(conn); - } + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index f61fb42062..963809c5d7 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -81,7 +81,7 @@ public class RdbmsCentralRepoFactory { * connectionPool object directly. */ public boolean initializeDatabaseSchema() { - + String createArtifactInstancesTableTemplate = getCreateArtifactInstancesTableTemplate(selectedPlatform); String instancesCaseIdIdx = getAddCaseIdIndexTemplate(); @@ -92,95 +92,88 @@ public class RdbmsCentralRepoFactory { // NOTE: the db_info table currenly only has 1 row, so having an index // provides no benefit. - Connection conn = null; - Statement stmt = null; - try { - conn = this.getEphemeralConnection(); + try (Connection conn = this.getEphemeralConnection();) { + if (null == conn) { LOGGER.log(Level.SEVERE, "Cannot initialize CR database, don't have a valid connection."); // NON-NLS return false; } - - stmt = conn.createStatement(); - // these setting PRAGMAs are SQLIte spcific - if (selectedPlatform == CentralRepoPlatforms.SQLITE) { - stmt.execute(PRAGMA_JOURNAL_WAL); - stmt.execute(PRAGMA_SYNC_OFF); - stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE); - stmt.execute(PRAGMA_ENCODING_UTF8); - stmt.execute(PRAGMA_PAGE_SIZE_4096); - stmt.execute(PRAGMA_FOREIGN_KEYS_ON); - } + try (Statement stmt = conn.createStatement();) { - // Create Organizations table - stmt.execute(getCreateOrganizationsTableStatement(selectedPlatform)); - - // Create Cases table and indexes - stmt.execute(getCreateCasesTableStatement(selectedPlatform)); - stmt.execute(getCasesOrgIdIndexStatement()); - stmt.execute(getCasesCaseUidIndexStatement()); - - stmt.execute(getCreateDataSourcesTableStatement(selectedPlatform)); - stmt.execute(getAddDataSourcesNameIndexStatement()); - stmt.execute(getAddDataSourcesObjectIdIndexStatement()); - - stmt.execute(getCreateReferenceSetsTableStatement(selectedPlatform)); - stmt.execute(getReferenceSetsOrgIdIndexTemplate()); - - stmt.execute(getCreateCorrelationTypesTableStatement(selectedPlatform)); - - stmt.execute(getCreateDbInfoTableStatement(selectedPlatform)); - stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')"); - stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); - stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')"); - stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); - - // Create account_types and accounts tab;es which are referred by X_instances tables - stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform)); - stmt.execute(getCreateAccountsTableStatement(selectedPlatform)); - - // Create a separate instance and reference table for each artifact type - List defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes(); - - String reference_type_dbname; - String instance_type_dbname; - for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) { - reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type); - instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type); - - stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname)); - stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname)); - stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname)); - stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname)); - stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname)); - stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname)); - - // FUTURE: allow more than the FILES type - if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) { - stmt.execute(String.format(getReferenceTypesTableTemplate(selectedPlatform), reference_type_dbname, reference_type_dbname)); - stmt.execute(String.format(getReferenceTypeValueIndexTemplate(), reference_type_dbname, reference_type_dbname)); - stmt.execute(String.format(getReferenceTypeValueKnownstatusIndexTemplate(), reference_type_dbname, reference_type_dbname)); + // these setting PRAGMAs are SQLIte spcific + if (selectedPlatform == CentralRepoPlatforms.SQLITE) { + stmt.execute(PRAGMA_JOURNAL_WAL); + stmt.execute(PRAGMA_SYNC_OFF); + stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE); + stmt.execute(PRAGMA_ENCODING_UTF8); + stmt.execute(PRAGMA_PAGE_SIZE_4096); + stmt.execute(PRAGMA_FOREIGN_KEYS_ON); } + + // Create Organizations table + stmt.execute(getCreateOrganizationsTableStatement(selectedPlatform)); + + // Create Cases table and indexes + stmt.execute(getCreateCasesTableStatement(selectedPlatform)); + stmt.execute(getCasesOrgIdIndexStatement()); + stmt.execute(getCasesCaseUidIndexStatement()); + + stmt.execute(getCreateDataSourcesTableStatement(selectedPlatform)); + stmt.execute(getAddDataSourcesNameIndexStatement()); + stmt.execute(getAddDataSourcesObjectIdIndexStatement()); + + stmt.execute(getCreateReferenceSetsTableStatement(selectedPlatform)); + stmt.execute(getReferenceSetsOrgIdIndexTemplate()); + + stmt.execute(getCreateCorrelationTypesTableStatement(selectedPlatform)); + + stmt.execute(getCreateDbInfoTableStatement(selectedPlatform)); + stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')"); + stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); + stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')"); + stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); + + // Create account_types and accounts tab;es which are referred by X_instances tables + stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform)); + stmt.execute(getCreateAccountsTableStatement(selectedPlatform)); + + // Create a separate instance and reference table for each artifact type + List defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + + String reference_type_dbname; + String instance_type_dbname; + for (CorrelationAttributeInstance.Type type : defaultCorrelationTypes) { + reference_type_dbname = CentralRepoDbUtil.correlationTypeToReferenceTableName(type); + instance_type_dbname = CentralRepoDbUtil.correlationTypeToInstanceTableName(type); + + stmt.execute(String.format(createArtifactInstancesTableTemplate, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesCaseIdIdx, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesDatasourceIdIdx, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesValueIdx, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesKnownStatusIdx, instance_type_dbname, instance_type_dbname)); + stmt.execute(String.format(instancesObjectIdIdx, instance_type_dbname, instance_type_dbname)); + + // FUTURE: allow more than the FILES type + if (type.getId() == CorrelationAttributeInstance.FILES_TYPE_ID) { + stmt.execute(String.format(getReferenceTypesTableTemplate(selectedPlatform), reference_type_dbname, reference_type_dbname)); + stmt.execute(String.format(getReferenceTypeValueIndexTemplate(), reference_type_dbname, reference_type_dbname)); + stmt.execute(String.format(getReferenceTypeValueKnownstatusIndexTemplate(), reference_type_dbname, reference_type_dbname)); + } + } + createPersonaTables(stmt); + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS + return false; + } catch (CentralRepoException ex) { + LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS + return false; } - - createPersonaTables(stmt); } catch (SQLException ex) { - LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS + LOGGER.log(Level.SEVERE, "Error connecting to database.", ex); // NON-NLS return false; - } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "Error getting default correlation types. Likely due to one or more Type's with an invalid db table name."); // NON-NLS - return false; - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ex2) { - LOGGER.log(Level.SEVERE, "Error closing statement.", ex2); - } - } - CentralRepoDbUtil.closeConnection(conn); } + return true; } @@ -190,17 +183,22 @@ public class RdbmsCentralRepoFactory { * @return True if success, False otherwise. */ public boolean insertDefaultDatabaseContent() { - Connection conn = this.getEphemeralConnection(); - if (null == conn) { + + boolean result; + try (Connection conn = this.getEphemeralConnection();) { + if (null == conn) { + return false; + } + + result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) + && CentralRepoDbUtil.insertDefaultOrganization(conn) + && insertDefaultPersonaTablesContent(conn); + + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in CR tables."), ex); return false; } - boolean result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) - && CentralRepoDbUtil.insertDefaultOrganization(conn) - && insertDefaultPersonaTablesContent(conn); - - - CentralRepoDbUtil.closeConnection(conn); return result; } @@ -849,24 +847,17 @@ public class RdbmsCentralRepoFactory { } else if (accountType == Account.Type.PHONE) { typeId = CorrelationAttributeInstance.PHONE_TYPE_ID; } else { - ResultSet resultSet = null; - - PreparedStatement preparedStatementQuery = null; String querySql = "SELECT * FROM correlation_types WHERE display_name=?"; - try { - preparedStatementQuery = conn.prepareStatement(querySql); + try ( PreparedStatement preparedStatementQuery = conn.prepareStatement(querySql)) { preparedStatementQuery.setString(1, accountType.getDisplayName()); - - resultSet = preparedStatementQuery.executeQuery(); - if (resultSet.next()) { - typeId = resultSet.getInt("id"); + try (ResultSet resultSet = preparedStatementQuery.executeQuery();) { + if (resultSet.next()) { + typeId = resultSet.getInt("id"); + } } } catch (SQLException ex) { LOGGER.log(Level.SEVERE, String.format("Failed to get correlation typeId for account type %s.", accountType.getTypeName()), ex); - } finally { - CentralRepoDbUtil.closeStatement(preparedStatementQuery); - CentralRepoDbUtil.closeResultSet(resultSet); - } + } } return typeId; From bcf728f1b7b368e98630cc0bd71ada7972682053 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 26 Feb 2020 15:53:26 -0500 Subject: [PATCH 41/77] Updated to support GeoArtifactHelper changes --- .../autopsy/geolocation/datamodel/Route.java | 10 ++++++---- .../autopsy/geolocation/datamodel/Track.java | 18 ++++++++++-------- .../autopsy/modules/drones/DATExtractor.java | 4 ++-- .../android/googlemaplocation.py | 2 +- 4 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index fa8dacf5d2..a08c343b6a 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -26,8 +26,9 @@ import java.util.Map; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints.GeoWaypoint; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList.GeoWaypoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList; /** * A Route represents a TSK_GPS_ROUTE artifact which has a start and end point @@ -42,6 +43,8 @@ public class Route extends GeoPath { // This list is not expected to change after construction so the // constructor will take care of creating an unmodifiable List private final List propertiesList; + + private static final TskGeoWaypointsUtil attributeUtil = new TskGeoWaypointsUtil(""); /** * Construct a route for the given artifact. @@ -117,8 +120,7 @@ public class Route extends GeoPath { } if (attribute != null) { - String value = attribute.getValueString(); - GeoWaypoints waypoints = GeoWaypoints.deserialize(value); + GeoWaypointList waypoints = attributeUtil.fromAttribute(attribute); Iterator waypointIter = waypoints.iterator(); while(waypointIter.hasNext()) { diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java index 33294d0d18..b6dc5a1528 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java @@ -27,8 +27,9 @@ import java.util.Map; import org.openide.util.NbBundle.Messages; import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint; /** * A GPS track with which wraps the TSK_GPS_TRACK artifact. @@ -37,6 +38,8 @@ public final class Track extends GeoPath{ private final Long startTimestamp; private final Long endTimeStamp; + + private static final TskGeoTrackpointsUtil attributeUtil = new TskGeoTrackpointsUtil(""); /** * Construct a new Track for the given artifact. @@ -60,7 +63,7 @@ public final class Track extends GeoPath{ private Track(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException { super(artifact, getTrackName(attributeMap)); - GeoTrackPoints points = getPointsList(attributeMap); + GeoTrackPointList points = getPointsList(attributeMap); buildPath(points); startTimestamp = points.getStartTime(); @@ -112,8 +115,8 @@ public final class Track extends GeoPath{ "# {0} - track name", "GEOTrack_point_label_header=Trackpoint for track: {0}" }) - private void buildPath(GeoTrackPoints points) throws GeoLocationDataException { - Iterator pointIter = points.iterator(); + private void buildPath(GeoTrackPointList points) throws GeoLocationDataException { + Iterator pointIter = points.iterator(); while(pointIter.hasNext()) { GeoTrackPoint point = pointIter.next(); addToPath(new TrackWaypoint(Bundle.GEOTrack_point_label_header(getLabel()), point)); @@ -128,11 +131,10 @@ public final class Track extends GeoPath{ * * @return GeoTrackPoint list empty list if the attribute was not found. */ - private GeoTrackPoints getPointsList(Map attributeMap) { + private GeoTrackPointList getPointsList(Map attributeMap) { BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS); if (attribute != null) { - String value = attribute.getValueString(); - return GeoTrackPoints.deserialize(value); + return attributeUtil.fromAttribute(attribute); } return null; diff --git a/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java index 68947be6fa..97cfbd40be 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java +++ b/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java @@ -41,11 +41,11 @@ import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestJobContext; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPointList.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint; import org.sleuthkit.datamodel.blackboardutils.GeoArtifactsHelper; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.datamodel.Blackboard.BlackboardException; -import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList; /** * Extract drone position data from DJI Phantom drones. diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index 330095c900..c04aadfba3 100644 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -42,7 +42,7 @@ from org.sleuthkit.datamodel import BlackboardAttribute from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper -from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypointList +from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil import GeoWaypointList import traceback import general From 61864b0d55af2a05ddd1d9dfefa4e38da35c50f4 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Thu, 27 Feb 2020 08:07:32 -0500 Subject: [PATCH 42/77] Address review comment. --- .../datamodel/CorrelationAttributeInstance.java | 2 +- .../centralrepository/datamodel/RdbmsCentralRepoFactory.java | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index a8974f8e5a..12fd9eac04 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -260,7 +260,7 @@ public class CorrelationAttributeInstance implements Serializable { for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { // Skip Phone and Email accounts as there are already Correlation types defined for those. if (type != Account.Type.EMAIL && type != Account.Type.PHONE) { - defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(correlationTypeId, type.getDisplayName(), type.getTypeName().toLowerCase(), true, true)); //NON-NLS + defaultCorrelationTypes.add(new CorrelationAttributeInstance.Type(correlationTypeId, type.getDisplayName(), type.getTypeName().toLowerCase() + "_acct", true, true)); //NON-NLS correlationTypeId++; } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index 963809c5d7..2fa248598e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -701,8 +701,10 @@ public class RdbmsCentralRepoFactory { + "created_date " + getBigIntType(selectedPlatform) + " ," + "modified_date " + getBigIntType(selectedPlatform) + " ," + "status_id integer NOT NULL," + + "examiner_id integer NOT NULL," + "CONSTRAINT uuid_unique UNIQUE(uuid)," - + "FOREIGN KEY (status_id) REFERENCES persona_status(status_id)" + + "FOREIGN KEY (status_id) REFERENCES persona_status(status_id), " + + "FOREIGN KEY (examiner_id) REFERENCES examiners(id)" + ")"; } From 605aa0086575c67361b59c36252266aa6ce52e58 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 27 Feb 2020 10:15:59 -0500 Subject: [PATCH 43/77] Updated based on review comments --- .../org/sleuthkit/autopsy/geolocation/datamodel/Route.java | 5 +---- .../org/sleuthkit/autopsy/geolocation/datamodel/Track.java | 4 +--- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index a08c343b6a..cda71c0e60 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -20,7 +20,6 @@ package org.sleuthkit.autopsy.geolocation.datamodel; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import org.openide.util.NbBundle.Messages; @@ -122,9 +121,7 @@ public class Route extends GeoPath { if (attribute != null) { GeoWaypointList waypoints = attributeUtil.fromAttribute(attribute); - Iterator waypointIter = waypoints.iterator(); - while(waypointIter.hasNext()) { - GeoWaypoint waypoint = waypointIter.next(); + for(GeoWaypoint waypoint: waypoints) { addToPath(new Waypoint(artifact, label, null, waypoint.getLatitude(), waypoint.getLongitude(), waypoint.getAltitude(), null, attributeMap, this)); } } else { diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java index b6dc5a1528..53ec4dfcbf 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java @@ -116,9 +116,7 @@ public final class Track extends GeoPath{ "GEOTrack_point_label_header=Trackpoint for track: {0}" }) private void buildPath(GeoTrackPointList points) throws GeoLocationDataException { - Iterator pointIter = points.iterator(); - while(pointIter.hasNext()) { - GeoTrackPoint point = pointIter.next(); + for(GeoTrackPoint point: points) { addToPath(new TrackWaypoint(Bundle.GEOTrack_point_label_header(getLabel()), point)); } } From 64709370987a64988d9a686df11dfb3e393b7978 Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Thu, 27 Feb 2020 10:52:29 -0500 Subject: [PATCH 44/77] Added missing geolocation detail lables --- .../geolocation/datamodel/Bundle.properties-MERGED | 2 ++ .../sleuthkit/autopsy/geolocation/datamodel/Track.java | 9 ++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED index 18627193b9..d603e85b7b 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Bundle.properties-MERGED @@ -6,4 +6,6 @@ Route_Label=As-the-crow-flies Route Route_point_label=Waypoints for route Route_Start_Label=Start SearchWaypoint_DisplayLabel=GPS Search +Track_distanceFromHome_displayName=Distance from home point +Track_distanceTraveled_displayName=Distance traveled TrackpointWaypoint_DisplayLabel=GPS Trackpoint diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java index 53ec4dfcbf..3760c6f1eb 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java @@ -21,7 +21,6 @@ package org.sleuthkit.autopsy.geolocation.datamodel; import java.util.ArrayList; import java.util.Collections; -import java.util.Iterator; import java.util.List; import java.util.Map; import org.openide.util.NbBundle.Messages; @@ -183,6 +182,10 @@ public final class Track extends GeoPath{ * * @return A list of Waypoint.properies. */ + @Messages({ + "Track_distanceTraveled_displayName=Distance traveled", + "Track_distanceFromHome_displayName=Distance from home point" + }) private List createPropertyList(GeoTrackPoint point) { List list = new ArrayList<>(); @@ -198,12 +201,12 @@ public final class Track extends GeoPath{ value = point.getDistanceTraveled(); if (value != null) { - list.add(new Property("", value.toString())); + list.add(new Property(Bundle.Track_distanceTraveled_displayName(), value.toString())); } value = point.getDistanceFromHP(); if (value != null) { - list.add(new Property("", value.toString())); + list.add(new Property(Bundle.Track_distanceFromHome_displayName(), value.toString())); } return list; From ede829860d8e948ea9e4f9d97f35a071036844ea Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Feb 2020 12:31:56 -0500 Subject: [PATCH 45/77] cleaned up dependencies --- .../autopsy/centralrepository/eventlisteners/Installer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 1609047e6d..37b2bb37a9 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -28,8 +28,6 @@ import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbManager; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil; -import org.sleuthkit.autopsy.centralrepository.datamodel.SqliteCentralRepoSettings; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; From 8e1cbce2d7188932e099b851071547f665cc7314 Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Thu, 27 Feb 2020 15:01:49 -0500 Subject: [PATCH 46/77] update to check if cr initialized outside of code base --- .../eventlisteners/Installer.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 37b2bb37a9..54a642b0dc 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -19,6 +19,7 @@ package org.sleuthkit.autopsy.centralrepository.eventlisteners; import java.lang.reflect.InvocationTargetException; +import java.util.Map; import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; @@ -66,10 +67,25 @@ public class Installer extends ModuleInstall { Case.addPropertyChangeListener(pcl); ieListener.installListeners(); - String initialized = ModuleSettings.getConfigSetting("CentralRepository", "initialized"); + + Map centralRepoSettings = ModuleSettings.getConfigSettings("CentralRepository"); + String initializedStr = centralRepoSettings.get("initialized"); + + // check to see if the repo has been initialized asking to setup cr + boolean initialized = Boolean.parseBoolean(initializedStr); + + // if it hasn't received that flag, check for a previous install where cr is already setup + if (!initialized) { + boolean prevRepo = Boolean.parseBoolean(centralRepoSettings.get("db.useCentralRepo")); + // if it has been previously set up and is in use, mark as previously initialized and save the settings + if (prevRepo) { + initialized = true; + ModuleSettings.setConfigSetting("CentralRepository", "initialized", "true"); + } + } // if central repository hasn't been previously initialized, initialize it - if (!Boolean.parseBoolean(initialized)) { + if (!initialized) { // if running with a GUI, prompt the user if (RuntimeProperties.runningWithGUI()) { try { From 9d26e2b69b03698e0a1da4beac09a5aebc5f191f Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Fri, 28 Feb 2020 10:11:15 -0500 Subject: [PATCH 47/77] reverting merged properties --- .../contextviewer/Bundle.properties-MERGED | 3 +++ .../autopsy/core/Bundle.properties-MERGED | 8 +------- .../corecomponents/Bundle.properties-MERGED | 6 +++--- .../autopsy/coreutils/Bundle.properties-MERGED | 4 +--- .../filesearch/Bundle.properties-MERGED | 4 ++-- .../autopsy/ingest/Bundle.properties-MERGED | 2 +- .../Bundle.properties-MERGED | 8 ++------ .../modules/exif/Bundle.properties-MERGED | 4 +--- .../fileextmismatch/Bundle.properties-MERGED | 18 +++++++++--------- .../hashdatabase/Bundle.properties-MERGED | 10 ++-------- .../interestingitems/Bundle.properties-MERGED | 4 ++-- .../photoreccarver/Bundle.properties-MERGED | 2 +- .../modules/html/Bundle.properties-MERGED | 6 +++--- .../recentactivity/Bundle.properties-MERGED | 11 ++++++++--- .../netbeans/core/startup/Bundle.properties | 4 ++-- .../core/windows/view/ui/Bundle.properties | 6 +++--- 16 files changed, 44 insertions(+), 56 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED index 79f4f61bfa..b29e7190fd 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED @@ -3,6 +3,7 @@ ContextViewer.downloadedOn=On ContextViewer.downloadSource=Downloaded from: ContextViewer.downloadURL=URL ContextViewer.email=Email +ContextViewer.file=File ContextViewer.jSourceGoToResultButton.text=Go to Result ContextViewer.jSourceTextLabel.text=jLabel2 ContextViewer.jSourceNameLabel.text=jSourceNameLabel @@ -11,5 +12,7 @@ ContextViewer.message=Message ContextViewer.messageFrom=From ContextViewer.messageOn=On ContextViewer.messageTo=To +ContextViewer.on=On +ContextViewer.recentDocs=Recent Documents: ContextViewer.title=Context ContextViewer.toolTip=Displays context for selected file. diff --git a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED index 0b16a9701f..c84f1f1b86 100755 --- a/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/core/Bundle.properties-MERGED @@ -3,13 +3,7 @@ Installer.closing.confirmationDialog.title=Ingest is Running # {0} - exception message Installer.closing.messageBox.caseCloseExceptionMessage=Error closing case: {0} OpenIDE-Module-Display-Category=Infrastructure -OpenIDE-Module-Long-Description=\ - This is the core Autopsy module.\n\n\ - The module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\n\ - The framework included in the module contains APIs for developing modules for ingest, viewers and reporting. \ - The modules can be deployed as Plugins using the Autopsy plugin installer.\n\ - This module should not be uninstalled - without it, Autopsy will not run.\n\n\ - For more information, see http://www.sleuthkit.org/autopsy/ +OpenIDE-Module-Long-Description=This is the core Autopsy module.\n\nThe module contains the core components needed for the bare application to run; the RCP platform, windowing GUI, sleuthkit bindings, datamodel / storage, explorer, result viewers, content viewers, ingest framework, reporting, and core tools, such as the file search.\n\nThe framework included in the module contains APIs for developing modules for ingest, viewers and reporting. The modules can be deployed as Plugins using the Autopsy plugin installer.\nThis module should not be uninstalled - without it, Autopsy will not run.\n\nFor more information, see http://www.sleuthkit.org/autopsy/ OpenIDE-Module-Name=Autopsy-Core OpenIDE-Module-Short-Description=Autopsy Core Module org_sleuthkit_autopsy_core_update_center=http://sleuthkit.org/autopsy/updates.xml diff --git a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED index 9f363b7723..f252420726 100755 --- a/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/corecomponents/Bundle.properties-MERGED @@ -63,9 +63,9 @@ DataContentViewerHex.totalPageLabel.text_1=100 DataContentViewerHex.pageLabel2.text=Page # Product Information panel -LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
+LBL_Description=
\n Product Version: {0} ({9})
Sleuth Kit Version: {7}
Netbeans RCP Build: {8}
Java: {1}; {2}
System: {3}; {4}; {5}
Userdir: {6}
Format_OperatingSystem_Value={0} version {1} running on {2} -LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2018.
+LBL_Copyright=
Autopsy™ is a digital forensics platform based on The Sleuth Kit™ and other tools.
Copyright © 2003-2018.
SortChooser.dialogTitle=Choose Sort Criteria ThumbnailViewChildren.progress.cancelling=(Cancelling) # {0} - file name @@ -95,7 +95,7 @@ DataResultViewerThumbnail.pageNextButton.text= DataResultViewerThumbnail.imagesLabel.text=Images: DataResultViewerThumbnail.imagesRangeLabel.text=- DataResultViewerThumbnail.pageNumLabel.text=- -DataResultViewerThumbnail.filePathLabel.text=\ \ \ +DataResultViewerThumbnail.filePathLabel.text=\ DataResultViewerThumbnail.goToPageLabel.text=Go to Page: DataResultViewerThumbnail.goToPageField.text= AdvancedConfigurationDialog.cancelButton.text=Cancel diff --git a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED index a0d535f8e6..18e279dd2c 100755 --- a/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/coreutils/Bundle.properties-MERGED @@ -30,9 +30,7 @@ PlatformUtil.getProcVmUsed.sigarNotInit.msg=Cannot get virt mem used, sigar not PlatformUtil.getProcVmUsed.gen.msg=Cannot get virt mem used, {0} PlatformUtil.getJvmMemInfo.usageText=JVM heap usage: {0}, JVM non-heap usage: {1} PlatformUtil.getPhysicalMemInfo.usageText=Physical memory usage (max, total, free): {0}, {1}, {2} -PlatformUtil.getAllMemUsageInfo.usageText={0}\n\ -{1}\n\ -Process Virtual Memory: {2} +PlatformUtil.getAllMemUsageInfo.usageText={0}\n{1}\nProcess Virtual Memory: {2} # {0} - file name ReadImageTask.mesageText=Reading image: {0} StringExtract.illegalStateException.cannotInit.msg=Unicode table not properly initialized, cannot instantiate StringExtract diff --git a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED index 0e732c1519..c585d0edf5 100755 --- a/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/filesearch/Bundle.properties-MERGED @@ -14,7 +14,7 @@ KnownStatusSearchPanel.knownCheckBox.text=Known Status: KnownStatusSearchPanel.knownBadOptionCheckBox.text=Notable KnownStatusSearchPanel.knownOptionCheckBox.text=Known (NSRL or other) KnownStatusSearchPanel.unknownOptionCheckBox.text=Unknown -DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected\! +DateSearchFilter.noneSelectedMsg.text=At least one date type must be selected! DateSearchPanel.dateCheckBox.text=Date: DateSearchPanel.jLabel4.text=Timezone: DateSearchPanel.jLabel3.text=*The date format is mm/dd/yyyy @@ -57,7 +57,7 @@ FileSearchPanel.search.results.details=Large number of matches may impact perfor FileSearchPanel.search.exception.noFilterSelected.msg=At least one filter must be selected. FileSearchPanel.search.validationErr.msg=Validation Error: {0} FileSearchPanel.emptyWhereClause.text=Invalid options, nothing to show. -KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected\! +KnownStatusSearchFilter.noneSelectedMsg.text=At least one known status must be selected! NameSearchFilter.emptyNameMsg.text=Must enter something for name search. SizeSearchPanel.sizeCompareComboBox.equalTo=equal to SizeSearchPanel.sizeCompareComboBox.greaterThan=greater than diff --git a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED index 9e4f612b6b..6be3e48e71 100755 --- a/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/ingest/Bundle.properties-MERGED @@ -140,7 +140,7 @@ IngestJob.cancelReason.outOfDiskSpace.text=Out of disk space IngestJob.cancelReason.servicesDown.text=Services Down IngestJob.cancelReason.caseClosed.text=Case closed IngestJobSettingsPanel.globalSettingsButton.text=Global Settings -gest +gest= IngestJobSettingsPanel.globalSettingsButton.actionCommand=Advanced IngestJobSettingsPanel.globalSettingsButton.text=Global Settings IngestJobSettingsPanel.pastJobsButton.text=History diff --git a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED index 4585d86449..4729293fb9 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/embeddedfileextractor/Bundle.properties-MERGED @@ -11,12 +11,7 @@ ExtractArchiveWithPasswordAction.progress.text=Unpacking contents of archive: {0 ExtractArchiveWithPasswordAction.prompt.text=Enter Password ExtractArchiveWithPasswordAction.prompt.title=Enter Password OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=\ - Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\n\ - Contents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\n\ - If the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\n\ - The extracted files are navigable in the directory tree.\n\n\ - The module is supported on Windows, Linux and Mac operating systems. +OpenIDE-Module-Long-Description=Embedded File Extraction Ingest Module\n\nThe Embedded File Extraction Ingest Module processes document files (such as doc, docx, ppt, pptx, xls, xlsx) and archive files (such as zip and others archive types supported by the 7zip extractor).\nContents of these files are extracted and the derived files are added back to the current ingest to be processed by the configured ingest modules.\nIf the derived file happens to be an archive file, it will be re-processed by the 7zip extractor - the extractor will process archive files N-levels deep.\n\nThe extracted files are navigable in the directory tree.\n\nThe module is supported on Windows, Linux and Mac operating systems. OpenIDE-Module-Name=Embedded File Extraction OpenIDE-Module-Short-Description=Embedded File Extraction Ingest Module EmbeddedFileExtractorIngestModule.SevenZipContentReadStream.seek.exception.invalidOrigin=Invalid seek origin: {0} @@ -28,6 +23,7 @@ EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg=Possib EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails=Compression ratio is {0}, skipping items in {1}. EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnMsg.zipBomb=Possible ZIP bomb detected: {0} EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnDetails.zipBomb=The archive is {0} levels deep, skipping processing of {1} +EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg=Unknown item path in archive: {0}, will use: {1} EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.msg=Not enough disk space to unpack archive item: {0}, {1} EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.details=The archive item is too large to unpack, skipping unpacking this item. EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.msg=Error unpacking {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED index f9a5a88b1b..4915d5a124 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/exif/Bundle.properties-MERGED @@ -2,9 +2,7 @@ CannotRunFileTypeDetection=Cannot run file type detection. ExifParserFileIngestModule.indexError.message=Failed to post EXIF Metadata artifact(s). ExifParserFileIngestModule.userContent.description=EXIF metadata exists for this file. OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=\ - Exif metadata ingest module. \n\n\ - The ingest module analyzes image files, extracts Exif information and posts the Exif data as results. +OpenIDE-Module-Long-Description=Exif metadata ingest module. \n\nThe ingest module analyzes image files, extracts Exif information and posts the Exif data as results. OpenIDE-Module-Name=ExifParser OpenIDE-Module-Short-Description=Exif metadata ingest module ExifParserFileIngestModule.moduleName.text=Exif Parser diff --git a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED index cfaadf1635..5063bd55fa 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/fileextmismatch/Bundle.properties-MERGED @@ -36,27 +36,27 @@ FileExtMismatchSettingsPanel.jLabel1.text=File Types: FileExtMismatchSettingsPanel.newExtButton.text=New Extension FileExtMismatchSettingsPanel.newMimePrompt.message=Add a new MIME file type: FileExtMismatchSettingsPanel.newMimePrompt.title=New MIME -FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty\! +FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.message=MIME type text is empty! FileExtMismatchSettingsPanel.newMimePrompt.emptyMime.title=Empty type -FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported\! +FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.message=MIME type not supported! FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotSupported.title=Type not supported -FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists\! +FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.message=MIME type already exists! FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeExists.title=Type already exists FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.message=MIME type is not detectable by this module. FileExtMismatchSettingsPanel.newMimePrompt.mimeTypeNotDetectable.title=Type not detectable -FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected\! +FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.message=No MIME type selected! FileExtMismatchSettingsPanel.removeTypeButton.noneSelected.title=No type selected FileExtMismatchSettingsPanel.newExtPrompt.message=Add an allowed extension: FileExtMismatchSettingsPanel.newExtPrompt.title=New allowed extension -FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty\! +FileExtMismatchSettingsPanel.newExtPrompt.empty.message=Extension text is empty! FileExtMismatchSettingsPanel.newExtPrompt.empty.title=Extension text empty -FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected\! +FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.message=No MIME type selected! FileExtMismatchSettingsPanel.newExtPrompt.noMimeType.title=No MIME type selected -FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists\! +FileExtMismatchSettingsPanel.newExtPrompt.extExists.message=Extension already exists! FileExtMismatchSettingsPanel.newExtPrompt.extExists.title=Extension already exists -FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected\! +FileExtMismatchSettingsPanel.removeExtButton.noneSelected.message=No extension selected! FileExtMismatchSettingsPanel.removeExtButton.noneSelected.title=No extension selected -FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected\! +FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.message=No MIME type selected! FileExtMismatchSettingsPanel.removeExtButton.noMimeTypeSelected.title=No MIME type selected FileExtMismatchSettingsPanel.removeTypeButton.toolTipText= FileExtMismatchModuleSettingsPanel.checkAllRadioButton.text=Check all file types diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED index 0b470ce6b1..44057d0016 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/Bundle.properties-MERGED @@ -49,10 +49,7 @@ ImportCentralRepoDbProgressDialog.errorParsingFile.message=Error parsing hash se ImportCentralRepoDbProgressDialog.linesProcessed.message=\ hashes processed ImportCentralRepoDbProgressDialog.title.text=Central Repository Import Progress OpenIDE-Module-Display-Category=Ingest Module -OpenIDE-Module-Long-Description=\ - Hash Set ingest module. \n\n\ - The ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\n\ - The module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration. +OpenIDE-Module-Long-Description=Hash Set ingest module. \n\nThe ingest module analyzes files in the disk image and marks them as "known" (based on NSRL hashset lookup for "known" files) and "bad / interesting" (based on one or more hash sets supplied by the user).\n\nThe module also contains additional non-ingest tools that are integrated in the GUI, such as file lookup by hash and hash set configuration. OpenIDE-Module-Name=HashDatabases OptionsCategory_Name_HashDatabase=Hash Sets OptionsCategory_Keywords_HashDatabase=Hash Sets @@ -181,10 +178,7 @@ HashDbSearchThread.name.searching=Searching HashDbSearchThread.noMoreFilesWithMD5Msg=No other files with the same MD5 hash were found. ModalNoButtons.indexingDbsTitle=Indexing hash sets ModalNoButtons.indexingDbTitle=Indexing hash set -ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \n\ -The generated index will be left unusable. If you choose to continue,\n\ - please delete the corresponding -md5.idx file in the hash folder.\n\ - Exit indexing? +ModalNoButtons.exitHashDbIndexingMsg=You are about to exit out of indexing your hash sets. \nThe generated index will be left unusable. If you choose to continue,\nplease delete the corresponding -md5.idx file in the hash folder.\nExit indexing? ModalNoButtons.dlgTitle.unfinishedIndexing=Unfinished Indexing ModalNoButtons.indexThis.currentlyIndexing1Db=Currently indexing 1 hash set ModalNoButtons.indexThese.currentlyIndexing1OfNDbs=Currently indexing 1 of {0} diff --git a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED index 1279d3642b..31a0690b82 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/interestingitems/Bundle.properties-MERGED @@ -83,8 +83,8 @@ FilesSetRulePanel.nameTextField.text= FilesSetRulePanel.ruleNameLabel.text=Rule Name (Optional): FilesSetRulePanel.messages.emptyNameCondition=You must specify a name pattern for this rule. FilesSetRulePanel.messages.invalidNameRegex=The name regular expression is not valid:\n\n{0} -FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, \", <, or > unless it is a regular expression. -FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, \", <, or > unless it is a regular expression. +FilesSetRulePanel.messages.invalidCharInName=The name cannot contain \\, /, :, *, ?, ", <, or > unless it is a regular expression. +FilesSetRulePanel.messages.invalidCharInPath=The path cannot contain \\, :, *, ?, ", <, or > unless it is a regular expression. FilesSetRulePanel.messages.invalidPathRegex=The path regular expression is not valid:\n\n{0} FilesSetDefsPanel.doFileSetsDialog.duplicateRuleSet.text=Rule set with name {0} already exists. FilesSetRulePanel.pathSeparatorInfoLabel.text=Folder must be in parent path. Use '/' to give consecutive names diff --git a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED index 87dacfc16c..2dc971a40d 100755 --- a/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/modules/photoreccarver/Bundle.properties-MERGED @@ -21,7 +21,7 @@ PhotoRecIngestModule.complete.totalParsetime=Total Parsing Time: PhotoRecIngestModule.complete.photoRecResults=PhotoRec Results PhotoRecIngestModule.NotEnoughDiskSpace.detail.msg=PhotoRec error processing {0} with {1} Not enough space on primary disk to save unallocated space. PhotoRecIngestModule.cancelledByUser=PhotoRec cancelled by user. -PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value \= {0} when scanning {1} +PhotoRecIngestModule.error.exitValue=PhotoRec carver returned error exit value = {0} when scanning {1} PhotoRecIngestModule.error.msg=Error processing {0} with PhotoRec carver. PhotoRecIngestModule.complete.numberOfErrors=Number of Errors while Carving: PhotoRecCarverIngestJobSettingsPanel.detectionSettingsLabel.text=PhotoRec Settings diff --git a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED index 32f6867f0c..0be7595111 100755 --- a/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/report/modules/html/Bundle.properties-MERGED @@ -5,8 +5,8 @@ ReportHTML.getName.text=HTML Report ReportHTML.getDesc.text=A report about results and tagged items in HTML format. ReportHTML.writeIndex.title=for case {0} ReportHTML.writeIndex.noFrames.msg=Your browser is not compatible with our frame setup. -ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, -ReportHTML.writeIndex.seeSum=and the summary page for a case summary. +ReportHTML.writeIndex.noFrames.seeNav=Please see the navigation page for artifact links, +ReportHTML.writeIndex.seeSum=and the summary page for a case summary. ReportHTML.writeNav.title=Report Navigation ReportHTML.writeNav.h1=Report Navigation ReportHTML.writeNav.summary=Case Summary @@ -16,7 +16,7 @@ ReportHTML.writeSum.caseNumber=Case Number: ReportHTML.writeSum.caseNumImages=Number of Images: ReportHTML.writeSum.examiner=Examiner: ReportHTML.writeSum.title=Case Summary -ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed\! +ReportHTML.writeSum.warningMsg=Warning, this report was run before ingest services completed! # # autopsy/test/scripts/regression.py._html_report_diff() uses reportGenOn.text, caseName, caseNum, # examiner as a regex signature to skip report.html and summary.html diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED index ebdce8a327..18deff87f4 100755 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/Bundle.properties-MERGED @@ -1,6 +1,7 @@ cannotBuildXmlParser=Unable to build XML parser: cannotLoadSEUQA=Unable to load Search Engine URL Query Analyzer settings file, SEUQAMappings.xml: cannotParseXml=Unable to parse XML file: +Chrome.getBookmark.errMsg.errAnalyzeFile={0}: Error while trying to analyze file: {1} ChromeCacheExtract_adding_artifacts_msg=Chrome Cache: Adding %d artifacts for analysis. ChromeCacheExtract_adding_extracted_files_msg=Chrome Cache: Adding %d extracted files for analysis. ChromeCacheExtract_loading_files_msg=Chrome Cache: Loading files from %s. @@ -13,9 +14,9 @@ ChromeCacheExtractor.progressMsg={0}: Extracting cache entry {1} of {2} entries DataSourceUsage_AndroidMedia=Android Media Card DataSourceUsage_DJU_Drone_DAT=DJI Internal SD Card DataSourceUsage_FlashDrive=Flash Drive -# {0} - OS name DataSourceUsageAnalyzer.customVolume.label=OS Drive ({0}) DataSourceUsageAnalyzer.parentModuleName=Recent Activity +Extract.dbConn.errMsg.failedToQueryDb={0}: Failed to query database. Extract.indexError.message=Failed to index artifact for keyword search. Extract.noOpenCase.errMsg=No open case available. ExtractEdge_getHistory_containerFileNotFound=Error while trying to analyze Edge history @@ -24,6 +25,11 @@ ExtractEdge_process_errMsg_errGettingWebCacheFiles=Error trying to retrieving Ed ExtractEdge_process_errMsg_spartanFail=Failure processing Microsoft Edge spartan.edb file ExtractEdge_process_errMsg_unableFindESEViewer=Unable to find ESEDatabaseViewer ExtractEdge_process_errMsg_webcacheFail=Failure processing Microsoft Edge WebCacheV01.dat file +ExtractIE.getBookmark.ere.noSpace=RecentActivity +ExtractIE.getBookmark.errMsg.errPostingBookmarks=Error posting Internet Explorer Bookmark artifacts. +ExtractIE.getCookie.errMsg.errPostingCookies=Error posting Internet Explorer Cookie artifacts. +ExtractIE.getHistory.errMsg.errPostingHistory=Error posting Internet Explorer History artifacts. +Extractor.errPostingArtifacts=Error posting {0} artifacts to the blackboard. ExtractOs.androidOs.label=Android ExtractOs.androidVolume.label=OS Drive (Android) ExtractOs.debianLinuxOs.label=Linux (Debian) @@ -90,7 +96,7 @@ Chrome.getLogin.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file Chrome.getAutofill.errMsg.errGettingFiles=Error when trying to get Chrome Web Data files. Chrome.getAutofill.errMsg.errAnalyzingFiles={0}: Error while trying to analyze file:{1} ExtractIE.moduleName.text=Internet Explorer -ExtractIE.getBookmark.errMsg.errGettingBookmarks={0}: Error getting Internet Explorer Bookmarks. +ExtractIE.getBookmark.errMsg.errGettingBookmarks=Error getting Internet Explorer Bookmarks. ExtractIE.parentModuleName.noSpace=RecentActivity ExtractIE.parentModuleName=Recent Activity ExtractIE.getURLFromIEBmkFile.errMsg={0}: Error parsing IE bookmark File {1} @@ -192,7 +198,6 @@ RecentDocumentsByLnk.parentModuleName.noSpace=RecentActivity RecentDocumentsByLnk.parentModuleName=Recent Activity RegRipperFullNotFound=Full version RegRipper executable not found. RegRipperNotFound=Autopsy RegRipper executable not found. -# {0} - file name SearchEngineURLQueryAnalyzer.init.exception.msg=Unable to find {0}. SearchEngineURLQueryAnalyzer.moduleName.text=Search Engine SearchEngineURLQueryAnalyzer.engineName.none=NONE 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 32871906e7..b20ccf5912 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 -#Thu, 27 Feb 2020 08:01:10 -0500 +#Tue, 12 Nov 2019 17:21:46 -0500 LBL_splash_window_title=Starting Autopsy SPLASH_HEIGHT=314 SPLASH_WIDTH=538 @@ -8,4 +8,4 @@ SplashRunningTextBounds=0,289,538,18 SplashRunningTextColor=0x0 SplashRunningTextFontSize=19 -currentVersion=Autopsy 4.14.0 +currentVersion=Autopsy 4.13.0 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 6c1cb1455b..998d3f715c 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,4 +1,4 @@ #Updated by build script -#Thu, 27 Feb 2020 08:01:10 -0500 -CTL_MainWindow_Title=Autopsy 4.14.0 -CTL_MainWindow_Title_No_Project=Autopsy 4.14.0 +#Tue, 12 Nov 2019 17:21:46 -0500 +CTL_MainWindow_Title=Autopsy 4.13.0 +CTL_MainWindow_Title_No_Project=Autopsy 4.13.0 From df3b7f559ad3ba35aa4334338089aed7decc5771 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 28 Feb 2020 12:45:16 -0500 Subject: [PATCH 48/77] Revert "6074-Standardize-file-paths-in-recent-documents-to-match-format-that-is-stored-in-autopsy-database" --- .../org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java | 1 - .../sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java | 1 - 2 files changed, 2 deletions(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index 0b119e00d0..dbad25708c 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -67,7 +67,6 @@ import java.util.Set; import java.util.HashSet; import static java.util.Locale.US; import static java.util.TimeZone.getTimeZone; -import org.apache.commons.io.FilenameUtils; import org.openide.util.Lookup; import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; import org.sleuthkit.autopsy.ingest.IngestModule.IngestModuleException; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index 42e5d2ecb0..331bb76524 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -30,7 +30,6 @@ import java.util.logging.Level; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import java.util.Collection; -import org.apache.commons.io.FilenameUtils; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.coreutils.JLNK; import org.sleuthkit.autopsy.coreutils.JLnkParser; From 9a27b155f89f809710355940c90917c60d605fa8 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Mon, 2 Mar 2020 13:12:52 -0500 Subject: [PATCH 49/77] 6013: Insert row in CR accounts table when accounts are created in Case database. --- .../datamodel/CRAccount.java | 136 ++++++++++++++ .../datamodel/CentralRepository.java | 27 ++- .../CorrelationAttributeInstance.java | 38 +++- .../CorrelationAttributeNormalizer.java | 23 ++- .../datamodel/CorrelationAttributeUtil.java | 35 +++- .../datamodel/RdbmsCentralRepo.java | 176 ++++++++++++++++-- 6 files changed, 410 insertions(+), 25 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java new file mode 100644 index 0000000000..97e3b93702 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java @@ -0,0 +1,136 @@ +/* + * Central Repository + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.centralrepository.datamodel; + +import org.sleuthkit.datamodel.Account; + + +/** + * This class abstracts an Account as stored in the CR database. + */ +public final class CRAccount { + + // primary key in the Accounts table in CR database + private final long account_id; + + private final CRAccountType crAccountType; + private final String typeSpecificID; + + /** + * A CRAccounType encapsulates an account type and the correlation type + * that it maps to. + */ + public static final class CRAccountType { + + // id is the primary key in the account_types table + private final int crAccountTypeID; + private final Account.Type acctType; + private final int correlationTypeID; + + CRAccountType(int acctTypeID, Account.Type acctType, int correlation_type_id) { + this.acctType = acctType; + this.correlationTypeID = correlation_type_id; + this.crAccountTypeID = acctTypeID; + } + + + /** + * @return the acctType + */ + public Account.Type getAcctType() { + return acctType; + } + + public int getCorrelationTypeId() { + return this.correlationTypeID; + } + + public int getCRAccountTypeId() { + return this.crAccountTypeID; + } + } + + public CRAccount(long account_id, CRAccountType accountType, String typeSpecificId) { + this.account_id = account_id; + this.crAccountType = accountType; + this.typeSpecificID = typeSpecificId; + } + + /** + * Gets unique identifier (assigned by a provider) for the account. Example + * includes an email address, a phone number, or a website username. + * + * @return type specific account id. + */ + public String getTypeSpecificID() { + return this.typeSpecificID; + } + + /** + * Gets the account type + * + * @return account type + */ + public CRAccountType getAccountType() { + return this.crAccountType; + } + + /** + * Gets the unique row id for this account in the database. + * + * @return unique row id. + */ + public long getAccountID() { + return this.account_id; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 43 * hash + (int) (this.account_id ^ (this.account_id >>> 32)); + hash = 43 * hash + (this.crAccountType != null ? this.crAccountType.hashCode() : 0); + hash = 43 * hash + (this.typeSpecificID != null ? this.typeSpecificID.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final CRAccount other = (CRAccount) obj; + if (this.account_id != other.getAccountID()) { + return false; + } + if ((this.typeSpecificID == null) ? (other.getTypeSpecificID() != null) : !this.typeSpecificID.equals(other.getTypeSpecificID())) { + return false; + } + if (this.crAccountType != other.getAccountType() && (this.crAccountType == null || !this.crAccountType.equals(other.getAccountType()))) { + return false; + } + return true; + } + +} diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index fe54161762..4fee5a0ddc 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Set; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.CRAccount.CRAccountType; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; /** @@ -808,8 +809,32 @@ public interface CentralRepository { /** * Returns list of all correlation types. * - * @return list of Correlation types + * @return list of Correlation types * @throws CentralRepoException */ List getCorrelationTypes() throws CentralRepoException; + + + /** + * Get CR account type by type name. + * + * @param accountTypeName account type name to look for + * @return CR account type + * @throws CentralRepoException + */ + CRAccountType getCRAccountTypeByName(String accountTypeName) throws CentralRepoException; + + /** + * Get an account from the accounts table matching the given type/ID. + * Inserts a row if one doesn't exists. + * + * @param crAccountType CR account type to look for or create + * @param accountUniqueID type specific unique account id + * @return CR account + * + * @throws CentralRepoException + */ + CRAccount getOrCreateCRAccount(CRAccount.CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException; + + } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index 12fd9eac04..d5461f4554 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -50,6 +50,7 @@ public class CorrelationAttributeInstance implements Serializable { private String comment; private TskData.FileKnown knownStatus; private Long objectId; + private Long accountId; public CorrelationAttributeInstance( CorrelationAttributeInstance.Type correlationType, @@ -73,6 +74,20 @@ public class CorrelationAttributeInstance implements Serializable { String comment, TskData.FileKnown knownStatus, Long fileObjectId + ) throws CentralRepoException, CorrelationAttributeNormalizationException { + this(type, value, -1, eamCase, eamDataSource, filePath, comment, knownStatus, fileObjectId, (long)-1); + } + CorrelationAttributeInstance( + Type type, + String value, + int instanceId, + CorrelationCase eamCase, + CorrelationDataSource eamDataSource, + String filePath, + String comment, + TskData.FileKnown knownStatus, + Long fileObjectId, + Long accountId ) throws CentralRepoException, CorrelationAttributeNormalizationException { if (filePath == null) { throw new CentralRepoException("file path is null"); @@ -88,6 +103,7 @@ public class CorrelationAttributeInstance implements Serializable { this.comment = comment; this.knownStatus = knownStatus; this.objectId = fileObjectId; + this.accountId = accountId; } public Boolean equals(CorrelationAttributeInstance otherInstance) { @@ -98,7 +114,8 @@ public class CorrelationAttributeInstance implements Serializable { && (this.getCorrelationDataSource().equals(otherInstance.getCorrelationDataSource())) && (this.getFilePath().equals(otherInstance.getFilePath())) && (this.getKnownStatus().equals(otherInstance.getKnownStatus())) - && (this.getComment().equals(otherInstance.getComment()))); + && (this.getComment().equals(otherInstance.getComment())) + && (this.getAccountId().equals(otherInstance.getAccountId()))); } @Override @@ -106,6 +123,7 @@ public class CorrelationAttributeInstance implements Serializable { return this.getID() + this.getCorrelationCase().getCaseUUID() + this.getCorrelationDataSource().getDeviceID() + + this.getAccountId() + this.getFilePath() + this.getCorrelationType().toString() + this.getCorrelationValue() @@ -210,6 +228,24 @@ public class CorrelationAttributeInstance implements Serializable { return objectId; } + /** + * Get the accountId of the account associated with the correlation + * attribute. + * + * @return the accountId of the account + */ + public Long getAccountId() { + return accountId; + } + + /** + * Set the accountId of the account associated with this correlation + * attribute. + */ + public void setAccountId(Long accountId) { + this.accountId = accountId; + } + // Type ID's for Default Correlation Types public static final int FILES_TYPE_ID = 0; public static final int DOMAIN_TYPE_ID = 1; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java index 4e5811a0c8..4154c579ca 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Optional; import org.apache.commons.validator.routines.DomainValidator; import org.apache.commons.validator.routines.EmailValidator; +import org.openide.util.Exceptions; /** * Provides functions for normalizing data by attribute type before insertion or @@ -76,11 +77,23 @@ final public class CorrelationAttributeNormalizer { return normalizeIccid(trimmedData); default: - final String errorMessage = String.format( - "Validator function not found for attribute type: %s", - attributeType.getDisplayName()); - throw new CorrelationAttributeNormalizationException(errorMessage); - } + try { + // If the atttribute is not one of the above + // but is one of the other default correlation types, then let the data go as is + List defaultCorrelationTypes = CorrelationAttributeInstance.getDefaultCorrelationTypes(); + for (CorrelationAttributeInstance.Type defaultCorrelationType : defaultCorrelationTypes) { + if (defaultCorrelationType.getId() == attributeType.getId()) { + return trimmedData; + } + } + final String errorMessage = String.format( + "Validator function not found for attribute type: %s", + attributeType.getDisplayName()); + throw new CorrelationAttributeNormalizationException(errorMessage); + } catch (CentralRepoException ex) { + throw new CorrelationAttributeNormalizationException(ex.getMessage()); + } + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 814169ef85..60af3dccaa 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -24,6 +24,7 @@ import java.util.logging.Level; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; +import org.sleuthkit.autopsy.centralrepository.datamodel.CRAccount.CRAccountType; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -222,6 +223,8 @@ public class CorrelationAttributeUtil { /** * Makes a correlation attribute instance for an account artifact. + * + * Also creates an account in the CR DB if it doesn't exist. * * IMPORTANT: The correlation attribute instance is NOT added to the central * repository by this method. @@ -239,13 +242,31 @@ public class CorrelationAttributeUtil { * * @return The correlation attribute instance. */ - private static void makeCorrAttrFromAcctArtifact(List corrAttrInstances, BlackboardArtifact acctArtifact) { - // RAMAN TODO: Convert TSK_ACCOUNT_TYPE attribute to correlation attribute type - // RAMAN TODO: Extract TSK_ID as value -// CorrelationAttributeInstance corrAttr = makeCorrAttr(acctArtifact, corrType, corrAttrValue); -// if (corrAttr != null) { -// corrAttrInstances.add(corrAttr); -// } + private static void makeCorrAttrFromAcctArtifact(List corrAttrInstances, BlackboardArtifact acctArtifact) throws TskCoreException, CentralRepoException { + + // Get the account type from the artifact + BlackboardAttribute accountTypeAttribute = acctArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE)); + String accountTypeStr = accountTypeAttribute.getValueString(); + + // Get the corresponding CRAccountType from the database. + CRAccountType crAccountType = CentralRepository.getInstance().getCRAccountTypeByName(accountTypeStr); + + int corrTypeId = crAccountType.getCorrelationTypeId(); + CorrelationAttributeInstance.Type corrType = CentralRepository.getInstance().getCorrelationTypeById(corrTypeId); + + // Get the account identifier + BlackboardAttribute accountIdAttribute = acctArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID)); + String accountIdStr = accountIdAttribute.getValueString(); + + // add/get the account and get its account_id. + CRAccount crAccount = CentralRepository.getInstance().getOrCreateCRAccount(crAccountType, accountIdStr); + + CorrelationAttributeInstance corrAttr = makeCorrAttr(acctArtifact, corrType, accountIdStr); + if (corrAttr != null) { + // set the account_id in correlation attribute + corrAttr.setAccountId(crAccount.getAccountID()); + corrAttrInstances.add(corrAttr); + } } /** diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index abbae1c867..993f3350b2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -41,12 +41,15 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; +import org.sleuthkit.autopsy.centralrepository.datamodel.CRAccount.CRAccountType; import static org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil.updateSchemaVersion; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.healthmonitor.HealthMonitor; import org.sleuthkit.autopsy.healthmonitor.TimingMetric; +import org.sleuthkit.datamodel.Account; import org.sleuthkit.datamodel.CaseDbSchemaVersionNumber; import org.sleuthkit.datamodel.TskData; @@ -71,6 +74,12 @@ abstract class RdbmsCentralRepo implements CentralRepository { private final Map> bulkArtifacts; private static final int CASE_CACHE_TIMEOUT = 5; private static final int DATA_SOURCE_CACHE_TIMEOUT = 5; + private static final int ACCOUNTS_CACHE_TIMEOUT = 5; + private static final Cache accountTypesCache = CacheBuilder.newBuilder().build(); + private static final Cache, CRAccount> accountsCache = CacheBuilder.newBuilder() + .expireAfterWrite(ACCOUNTS_CACHE_TIMEOUT, TimeUnit.MINUTES). + build(); + private static final Cache typeCache = CacheBuilder.newBuilder().build(); private static final Cache caseCacheByUUID = CacheBuilder.newBuilder() .expireAfterWrite(CASE_CACHE_TIMEOUT, TimeUnit.MINUTES). @@ -993,22 +1002,22 @@ abstract class RdbmsCentralRepo implements CentralRepository { public void addArtifactInstance(CorrelationAttributeInstance eamArtifact) throws CentralRepoException { checkAddArtifactInstanceNulls(eamArtifact); - Connection conn = connect(); + - PreparedStatement preparedStatement = null; + // @@@ We should cache the case and data source IDs in memory String tableName = CentralRepoDbUtil.correlationTypeToInstanceTableName(eamArtifact.getCorrelationType()); String sql = "INSERT INTO " + tableName - + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id) " - + "VALUES (?, ?, ?, ?, ?, ?, ?) " + + "(case_id, data_source_id, value, file_path, known_status, comment, file_obj_id, account_id) " + + "VALUES (?, ?, ?, ?, ?, ?, ?, ?) " + getConflictClause(); - try { - preparedStatement = conn.prepareStatement(sql); - + try (Connection conn = connect(); + PreparedStatement preparedStatement = conn.prepareStatement(sql);) { + if (!eamArtifact.getCorrelationValue().isEmpty()) { preparedStatement.setInt(1, eamArtifact.getCorrelationCase().getID()); preparedStatement.setInt(2, eamArtifact.getCorrelationDataSource().getID()); @@ -1022,18 +1031,163 @@ abstract class RdbmsCentralRepo implements CentralRepository { preparedStatement.setString(6, eamArtifact.getComment()); } preparedStatement.setLong(7, eamArtifact.getFileObjectId()); + + if (eamArtifact.getAccountId() >= 0) { + preparedStatement.setLong(8, eamArtifact.getAccountId()); + } else { + preparedStatement.setNull(8, Types.INTEGER); + } preparedStatement.executeUpdate(); } } catch (SQLException ex) { throw new CentralRepoException("Error inserting new artifact into artifacts table.", ex); // NON-NLS - } finally { - CentralRepoDbUtil.closeStatement(preparedStatement); - CentralRepoDbUtil.closeConnection(conn); - } + } } + /** + * Gets the CR account for the given account type and account ID. + * Create a new account first, if one doesn't exist + * + * @param accountType account type + * @param accountUniqueID unique account identifier + * + * @return A matching account, either existing or newly created. + * + * @throws TskCoreException exception thrown if a critical error occurs + * within TSK core + */ + @Override + public CRAccount getOrCreateCRAccount(CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException { + // Get the account fom the accounts table + CRAccount account = getCRAccount(crAccountType, accountUniqueID); + + // account not found in the table, create it + if (null == account) { + + String query = "INSERT INTO accounts (account_type_id, account_unique_identifier) " + + "VALUES ( " + crAccountType.getCRAccountTypeId() + ", '" + + accountUniqueID + "' )"; + + try (Connection connection = connect(); + Statement s = connection.createStatement();) { + + s.execute(query); + // get the account from the db - should exist now. + account = getCRAccount(crAccountType, accountUniqueID); + } catch (SQLException ex) { + throw new CentralRepoException("Error adding an account to CR database.", ex); + } + } + + return account; + } + + + @Override + public CRAccountType getCRAccountTypeByName(String accountTypeName) throws CentralRepoException { + try { + return accountTypesCache.get(accountTypeName, () -> getCRAccountTypeFromDb(accountTypeName)); + } catch (CacheLoader.InvalidCacheLoadException | ExecutionException ex) { + throw new CentralRepoException("Error looking up CR account type in cache.", ex); + } + } + + + /** + * Gets the CR account type for the specified type name. + * + * @param accountTypeName account type name to look for + * @return CR account type + * + * @throws CentralRepoException + */ + private CRAccountType getCRAccountTypeFromDb(String accountTypeName) throws CentralRepoException { + + String sql = "SELECT * FROM account_types WHERE type_name = ?"; + try ( Connection conn = connect(); + PreparedStatement preparedStatement = conn.prepareStatement(sql);) { + + preparedStatement.setString(1, accountTypeName); + try (ResultSet resultSet = preparedStatement.executeQuery();) { + if (resultSet.next()) { + Account.Type acctType = new Account.Type(accountTypeName, resultSet.getString("display_name")); + CRAccountType crAccountType = new CRAccountType(resultSet.getInt("id"), acctType, resultSet.getInt("correlation_type_id")); + accountTypesCache.put(accountTypeName, crAccountType); + return crAccountType; + } else { + throw new CentralRepoException("Failed to find entry for account type = " + accountTypeName); + } + } + } catch (SQLException ex) { + throw new CentralRepoException("Error getting correlation type by id.", ex); // NON-NLS + } + } + + /** + * Get the CR account with the given account type and the unique account identifier. + * Looks in the cache first. + * If not found in cache, reads from the database and saves in cache. + * + * Returns null if the account is not found in the cache and not in the database. + * + * @param crAccountType account type to look for + * @param accountUniqueID unique account id + * @return CRAccount for the give type/id. May return null if not found. + * + * @throws CentralRepoException + */ + private CRAccount getCRAccount(CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException { + + CRAccount crAccount = accountsCache.getIfPresent(Pair.of(crAccountType, accountUniqueID)); + if (crAccount == null) { + crAccount = getCRAccountFromDb(crAccountType, accountUniqueID); + if (crAccount != null) { + accountsCache.put(Pair.of(crAccountType, accountUniqueID), crAccount); + } + } + + return crAccount; + } + + + /** + * Get the Account with the given account type and account identifier, + * from the database. + * + * @param accountType account type + * @param accountUniqueID unique account identifier + * + * @return Account, returns NULL is no matching account found + * + * @throws TskCoreException exception thrown if a critical error occurs + * within TSK core + */ + private CRAccount getCRAccountFromDb(CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException { + + CRAccount account = null; + + String sql = "SELECT * FROM accounts WHERE account_type_id = ? AND account_unique_identifier = ?"; + try ( Connection connection = connect(); + PreparedStatement preparedStatement = connection.prepareStatement(sql);) { + + preparedStatement.setInt(1, crAccountType.getCRAccountTypeId()); + preparedStatement.setString(2, accountUniqueID); + + try (ResultSet resultSet = preparedStatement.executeQuery();) { + if (resultSet.next()) { + account = new CRAccount(resultSet.getInt("id"), crAccountType, resultSet.getString("account_unique_identifier")); //NON-NLS + } + } + } catch (SQLException ex) { + throw new CentralRepoException("Error getting account type id", ex); + } + + return account; + } + + private void checkAddArtifactInstanceNulls(CorrelationAttributeInstance eamArtifact) throws CentralRepoException { if (eamArtifact == null) { throw new CentralRepoException("CorrelationAttribute is null"); From 863f5f3f499f9e2b468298461c137e5b6d4f4285 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Mon, 2 Mar 2020 14:14:01 -0500 Subject: [PATCH 50/77] Address Codacy comments. --- .../datamodel/CorrelationAttributeNormalizer.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java index 4154c579ca..f68dab484a 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeNormalizer.java @@ -23,7 +23,6 @@ import java.util.List; import java.util.Optional; import org.apache.commons.validator.routines.DomainValidator; import org.apache.commons.validator.routines.EmailValidator; -import org.openide.util.Exceptions; /** * Provides functions for normalizing data by attribute type before insertion or @@ -91,7 +90,7 @@ final public class CorrelationAttributeNormalizer { attributeType.getDisplayName()); throw new CorrelationAttributeNormalizationException(errorMessage); } catch (CentralRepoException ex) { - throw new CorrelationAttributeNormalizationException(ex.getMessage()); + throw new CorrelationAttributeNormalizationException("Failed to get default correlation types.", ex); } } } From 0bc92dd080ff95800a3109f97850f1831858f741 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 2 Mar 2020 15:50:26 -0500 Subject: [PATCH 51/77] Add back commits that were accidently removed in recent revert of other unwanted code --- .../org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java | 1 + .../sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java index dbad25708c..08b575c572 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/ExtractRegistry.java @@ -36,6 +36,7 @@ import java.util.logging.Level; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; +import org.apache.commons.io.FilenameUtils; import org.openide.modules.InstalledFileLocator; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.ExecUtil; diff --git a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java index 331bb76524..2b93720fcd 100644 --- a/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java +++ b/RecentActivity/src/org/sleuthkit/autopsy/recentactivity/RecentDocumentsByLnk.java @@ -26,7 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.logging.Level; - +import org.apache.commons.io.FilenameUtils; import org.openide.util.NbBundle; import org.sleuthkit.autopsy.coreutils.Logger; import java.util.Collection; From 54ea1f9265f323cf21f0ee0dfb940d913fbfee5b Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Tue, 3 Mar 2020 10:25:10 -0500 Subject: [PATCH 52/77] Addressed review comments. --- ...CRAccount.java => CentralRepoAccount.java} | 63 ++++++++++--------- .../datamodel/CentralRepository.java | 8 +-- .../CorrelationAttributeInstance.java | 2 +- .../datamodel/CorrelationAttributeUtil.java | 12 ++-- .../datamodel/RdbmsCentralRepo.java | 36 +++++------ 5 files changed, 61 insertions(+), 60 deletions(-) rename Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/{CRAccount.java => CentralRepoAccount.java} (54%) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java similarity index 54% rename from Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java rename to Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java index 97e3b93702..70d6f99e37 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CRAccount.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepoAccount.java @@ -24,29 +24,30 @@ import org.sleuthkit.datamodel.Account; /** * This class abstracts an Account as stored in the CR database. */ -public final class CRAccount { +public final class CentralRepoAccount { // primary key in the Accounts table in CR database - private final long account_id; + private final long accountId; - private final CRAccountType crAccountType; - private final String typeSpecificID; + private final CentralRepoAccountType accountType; + // type specifc unique account id + private final String typeSpecificId; /** - * A CRAccounType encapsulates an account type and the correlation type + * Encapsulates a central repo account type and the correlation type * that it maps to. */ - public static final class CRAccountType { + public static final class CentralRepoAccountType { // id is the primary key in the account_types table - private final int crAccountTypeID; + private final int accountTypeId; private final Account.Type acctType; - private final int correlationTypeID; + private final int correlationTypeId; - CRAccountType(int acctTypeID, Account.Type acctType, int correlation_type_id) { + CentralRepoAccountType(int acctTypeID, Account.Type acctType, int correlationTypeId) { this.acctType = acctType; - this.correlationTypeID = correlation_type_id; - this.crAccountTypeID = acctTypeID; + this.correlationTypeId = correlationTypeId; + this.accountTypeId = acctTypeID; } @@ -58,18 +59,18 @@ public final class CRAccount { } public int getCorrelationTypeId() { - return this.correlationTypeID; + return this.correlationTypeId; } - public int getCRAccountTypeId() { - return this.crAccountTypeID; + public int getAccountTypeId() { + return this.accountTypeId; } } - public CRAccount(long account_id, CRAccountType accountType, String typeSpecificId) { - this.account_id = account_id; - this.crAccountType = accountType; - this.typeSpecificID = typeSpecificId; + public CentralRepoAccount(long accountId, CentralRepoAccountType accountType, String typeSpecificId) { + this.accountId = accountId; + this.accountType = accountType; + this.typeSpecificId = typeSpecificId; } /** @@ -78,8 +79,8 @@ public final class CRAccount { * * @return type specific account id. */ - public String getTypeSpecificID() { - return this.typeSpecificID; + public String getTypeSpecificId() { + return this.typeSpecificId; } /** @@ -87,8 +88,8 @@ public final class CRAccount { * * @return account type */ - public CRAccountType getAccountType() { - return this.crAccountType; + public CentralRepoAccountType getAccountType() { + return this.accountType; } /** @@ -96,16 +97,16 @@ public final class CRAccount { * * @return unique row id. */ - public long getAccountID() { - return this.account_id; + public long getAccountId() { + return this.accountId; } @Override public int hashCode() { int hash = 5; - hash = 43 * hash + (int) (this.account_id ^ (this.account_id >>> 32)); - hash = 43 * hash + (this.crAccountType != null ? this.crAccountType.hashCode() : 0); - hash = 43 * hash + (this.typeSpecificID != null ? this.typeSpecificID.hashCode() : 0); + hash = 43 * hash + (int) (this.accountId ^ (this.accountId >>> 32)); + hash = 43 * hash + (this.accountType != null ? this.accountType.hashCode() : 0); + hash = 43 * hash + (this.typeSpecificId != null ? this.typeSpecificId.hashCode() : 0); return hash; } @@ -120,14 +121,14 @@ public final class CRAccount { if (getClass() != obj.getClass()) { return false; } - final CRAccount other = (CRAccount) obj; - if (this.account_id != other.getAccountID()) { + final CentralRepoAccount other = (CentralRepoAccount) obj; + if (this.accountId != other.getAccountId()) { return false; } - if ((this.typeSpecificID == null) ? (other.getTypeSpecificID() != null) : !this.typeSpecificID.equals(other.getTypeSpecificID())) { + if ((this.typeSpecificId == null) ? (other.getTypeSpecificId() != null) : !this.typeSpecificId.equals(other.getTypeSpecificId())) { return false; } - if (this.crAccountType != other.getAccountType() && (this.crAccountType == null || !this.crAccountType.equals(other.getAccountType()))) { + if (this.accountType != other.getAccountType() && (this.accountType == null || !this.accountType.equals(other.getAccountType()))) { return false; } return true; diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java index 4fee5a0ddc..904712c73c 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CentralRepository.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Set; import org.sleuthkit.datamodel.TskData; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.centralrepository.datamodel.CRAccount.CRAccountType; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType; import org.sleuthkit.autopsy.coordinationservice.CoordinationService; /** @@ -816,13 +816,13 @@ public interface CentralRepository { /** - * Get CR account type by type name. + * Get account type by type name. * * @param accountTypeName account type name to look for * @return CR account type * @throws CentralRepoException */ - CRAccountType getCRAccountTypeByName(String accountTypeName) throws CentralRepoException; + CentralRepoAccountType getAccountTypeByName(String accountTypeName) throws CentralRepoException; /** * Get an account from the accounts table matching the given type/ID. @@ -834,7 +834,7 @@ public interface CentralRepository { * * @throws CentralRepoException */ - CRAccount getOrCreateCRAccount(CRAccount.CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException; + CentralRepoAccount getOrCreateAccount(CentralRepoAccount.CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java index d5461f4554..1ab978bc84 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeInstance.java @@ -242,7 +242,7 @@ public class CorrelationAttributeInstance implements Serializable { * Set the accountId of the account associated with this correlation * attribute. */ - public void setAccountId(Long accountId) { + void setAccountId(Long accountId) { this.accountId = accountId; } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 60af3dccaa..04aa6fc16e 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -24,7 +24,7 @@ import java.util.logging.Level; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.centralrepository.datamodel.CRAccount.CRAccountType; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.BlackboardArtifact; @@ -248,8 +248,8 @@ public class CorrelationAttributeUtil { BlackboardAttribute accountTypeAttribute = acctArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE)); String accountTypeStr = accountTypeAttribute.getValueString(); - // Get the corresponding CRAccountType from the database. - CRAccountType crAccountType = CentralRepository.getInstance().getCRAccountTypeByName(accountTypeStr); + // Get the corresponding CentralRepoAccountType from the database. + CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr); int corrTypeId = crAccountType.getCorrelationTypeId(); CorrelationAttributeInstance.Type corrType = CentralRepository.getInstance().getCorrelationTypeById(corrTypeId); @@ -258,13 +258,13 @@ public class CorrelationAttributeUtil { BlackboardAttribute accountIdAttribute = acctArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID)); String accountIdStr = accountIdAttribute.getValueString(); - // add/get the account and get its account_id. - CRAccount crAccount = CentralRepository.getInstance().getOrCreateCRAccount(crAccountType, accountIdStr); + // add/get the account and get its accountId. + CentralRepoAccount crAccount = CentralRepository.getInstance().getOrCreateAccount(crAccountType, accountIdStr); CorrelationAttributeInstance corrAttr = makeCorrAttr(acctArtifact, corrType, accountIdStr); if (corrAttr != null) { // set the account_id in correlation attribute - corrAttr.setAccountId(crAccount.getAccountID()); + corrAttr.setAccountId(crAccount.getAccountId()); corrAttrInstances.add(corrAttr); } } diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java index 993f3350b2..93f6268979 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepo.java @@ -44,7 +44,7 @@ import java.util.logging.Level; import org.apache.commons.lang3.tuple.Pair; import org.openide.util.NbBundle.Messages; import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.centralrepository.datamodel.CRAccount.CRAccountType; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount.CentralRepoAccountType; import static org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoDbUtil.updateSchemaVersion; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.healthmonitor.HealthMonitor; @@ -75,8 +75,8 @@ abstract class RdbmsCentralRepo implements CentralRepository { private static final int CASE_CACHE_TIMEOUT = 5; private static final int DATA_SOURCE_CACHE_TIMEOUT = 5; private static final int ACCOUNTS_CACHE_TIMEOUT = 5; - private static final Cache accountTypesCache = CacheBuilder.newBuilder().build(); - private static final Cache, CRAccount> accountsCache = CacheBuilder.newBuilder() + private static final Cache accountTypesCache = CacheBuilder.newBuilder().build(); + private static final Cache, CentralRepoAccount> accountsCache = CacheBuilder.newBuilder() .expireAfterWrite(ACCOUNTS_CACHE_TIMEOUT, TimeUnit.MINUTES). build(); @@ -1047,7 +1047,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { } /** - * Gets the CR account for the given account type and account ID. + * Gets the Central Repo account for the given account type and account ID. * Create a new account first, if one doesn't exist * * @param accountType account type @@ -1059,15 +1059,15 @@ abstract class RdbmsCentralRepo implements CentralRepository { * within TSK core */ @Override - public CRAccount getOrCreateCRAccount(CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException { + public CentralRepoAccount getOrCreateAccount(CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException { // Get the account fom the accounts table - CRAccount account = getCRAccount(crAccountType, accountUniqueID); + CentralRepoAccount account = getAccount(crAccountType, accountUniqueID); // account not found in the table, create it if (null == account) { String query = "INSERT INTO accounts (account_type_id, account_unique_identifier) " - + "VALUES ( " + crAccountType.getCRAccountTypeId() + ", '" + + "VALUES ( " + crAccountType.getAccountTypeId() + ", '" + accountUniqueID + "' )"; try (Connection connection = connect(); @@ -1075,7 +1075,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { s.execute(query); // get the account from the db - should exist now. - account = getCRAccount(crAccountType, accountUniqueID); + account = getAccount(crAccountType, accountUniqueID); } catch (SQLException ex) { throw new CentralRepoException("Error adding an account to CR database.", ex); } @@ -1086,7 +1086,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { @Override - public CRAccountType getCRAccountTypeByName(String accountTypeName) throws CentralRepoException { + public CentralRepoAccountType getAccountTypeByName(String accountTypeName) throws CentralRepoException { try { return accountTypesCache.get(accountTypeName, () -> getCRAccountTypeFromDb(accountTypeName)); } catch (CacheLoader.InvalidCacheLoadException | ExecutionException ex) { @@ -1103,7 +1103,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { * * @throws CentralRepoException */ - private CRAccountType getCRAccountTypeFromDb(String accountTypeName) throws CentralRepoException { + private CentralRepoAccountType getCRAccountTypeFromDb(String accountTypeName) throws CentralRepoException { String sql = "SELECT * FROM account_types WHERE type_name = ?"; try ( Connection conn = connect(); @@ -1113,7 +1113,7 @@ abstract class RdbmsCentralRepo implements CentralRepository { try (ResultSet resultSet = preparedStatement.executeQuery();) { if (resultSet.next()) { Account.Type acctType = new Account.Type(accountTypeName, resultSet.getString("display_name")); - CRAccountType crAccountType = new CRAccountType(resultSet.getInt("id"), acctType, resultSet.getInt("correlation_type_id")); + CentralRepoAccountType crAccountType = new CentralRepoAccountType(resultSet.getInt("id"), acctType, resultSet.getInt("correlation_type_id")); accountTypesCache.put(accountTypeName, crAccountType); return crAccountType; } else { @@ -1134,13 +1134,13 @@ abstract class RdbmsCentralRepo implements CentralRepository { * * @param crAccountType account type to look for * @param accountUniqueID unique account id - * @return CRAccount for the give type/id. May return null if not found. + * @return CentralRepoAccount for the give type/id. May return null if not found. * * @throws CentralRepoException */ - private CRAccount getCRAccount(CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException { + private CentralRepoAccount getAccount(CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException { - CRAccount crAccount = accountsCache.getIfPresent(Pair.of(crAccountType, accountUniqueID)); + CentralRepoAccount crAccount = accountsCache.getIfPresent(Pair.of(crAccountType, accountUniqueID)); if (crAccount == null) { crAccount = getCRAccountFromDb(crAccountType, accountUniqueID); if (crAccount != null) { @@ -1164,20 +1164,20 @@ abstract class RdbmsCentralRepo implements CentralRepository { * @throws TskCoreException exception thrown if a critical error occurs * within TSK core */ - private CRAccount getCRAccountFromDb(CRAccountType crAccountType, String accountUniqueID) throws CentralRepoException { + private CentralRepoAccount getCRAccountFromDb(CentralRepoAccountType crAccountType, String accountUniqueID) throws CentralRepoException { - CRAccount account = null; + CentralRepoAccount account = null; String sql = "SELECT * FROM accounts WHERE account_type_id = ? AND account_unique_identifier = ?"; try ( Connection connection = connect(); PreparedStatement preparedStatement = connection.prepareStatement(sql);) { - preparedStatement.setInt(1, crAccountType.getCRAccountTypeId()); + preparedStatement.setInt(1, crAccountType.getAccountTypeId()); preparedStatement.setString(2, accountUniqueID); try (ResultSet resultSet = preparedStatement.executeQuery();) { if (resultSet.next()) { - account = new CRAccount(resultSet.getInt("id"), crAccountType, resultSet.getString("account_unique_identifier")); //NON-NLS + account = new CentralRepoAccount(resultSet.getInt("id"), crAccountType, resultSet.getString("account_unique_identifier")); //NON-NLS } } } catch (SQLException ex) { From ecca495943d98d3ba5534ea3d3ca43d523c0ee9d Mon Sep 17 00:00:00 2001 From: Greg DiCristofaro Date: Tue, 3 Mar 2020 13:15:42 -0500 Subject: [PATCH 53/77] use content by id to fetch display name for BlackboardArtifactNode --- .../sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java index b58bb915d0..17b8248f06 100644 --- a/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java +++ b/Core/src/org/sleuthkit/autopsy/datamodel/BlackboardArtifactNode.java @@ -323,7 +323,8 @@ public class BlackboardArtifactNode extends AbstractContentNode Date: Tue, 3 Mar 2020 12:53:49 -0500 Subject: [PATCH 54/77] 6090-6048 fix matisse issue with cvttopcomponent --- .../communications/CVTTopComponent.form | 44 +------------------ .../communications/CVTTopComponent.java | 39 ++++++---------- 2 files changed, 16 insertions(+), 67 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form index c11d0c335c..6b770eda70 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.form @@ -16,9 +16,9 @@ - + - + @@ -40,10 +40,6 @@ - - - - @@ -78,42 +74,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java index a11fde5622..c43e28155a 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java @@ -55,15 +55,18 @@ public final class CVTTopComponent extends TopComponent { private static final long serialVersionUID = 1L; private boolean filtersVisible = true; private final RelationshipBrowser relationshipBrowser = new RelationshipBrowser(); + private final AccountsBrowser accountsBrowser = new AccountsBrowser(relationshipBrowser); private CommunicationsFilter currentFilter; + private final VisualizationPanel vizPanel = new VisualizationPanel(relationshipBrowser); + private final FiltersPanel filtersPane = new FiltersPanel(); @ThreadConfined(type = ThreadConfined.ThreadType.AWT) public CVTTopComponent() { initComponents(); - + splitPane.setRightComponent(relationshipBrowser); splitPane.setDividerLocation(0.25); - + setName(Bundle.CVTTopComponent_name()); /* @@ -76,15 +79,14 @@ public final class CVTTopComponent extends TopComponent { // Make sure the Global Actions Context is proxying the selection of the active tab. browseVisualizeTabPane.addChangeListener(changeEvent -> { Component selectedComponent = browseVisualizeTabPane.getSelectedComponent(); - if(selectedComponent instanceof Lookup.Provider) { - Lookup lookup = ((Lookup.Provider)selectedComponent).getLookup(); + if (selectedComponent instanceof Lookup.Provider) { + Lookup lookup = ((Lookup.Provider) selectedComponent).getLookup(); proxyLookup.setNewLookups(lookup); } - + relationshipBrowser.setSelectionInfo(new SelectionInfo(new HashSet<>(), new HashSet<>(), currentFilter)); }); - - + /* * Connect the filtersPane to the accountsBrowser and visualizaionPanel * via an Eventbus @@ -93,7 +95,7 @@ public final class CVTTopComponent extends TopComponent { CVTEvents.getCVTEventBus().register(vizPanel); CVTEvents.getCVTEventBus().register(accountsBrowser); CVTEvents.getCVTEventBus().register(filtersPane); - + filterTabbedPane.setIconAt(0, new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-left.png"))); filterTabbedPane.setTitleAt(0, ""); } @@ -102,7 +104,7 @@ public final class CVTTopComponent extends TopComponent { void pinAccount(CVTEvents.PinAccountsEvent pinEvent) { browseVisualizeTabPane.setSelectedIndex(1); } - + @Subscribe void handle(final CVTEvents.FilterChangeEvent filterChangeEvent) { currentFilter = filterChangeEvent.getNewFilter(); @@ -118,11 +120,8 @@ public final class CVTTopComponent extends TopComponent { filterTabbedPane = new JTabbedPane(); filterTabPanel = new JPanel(); - filtersPane = new FiltersPanel(); splitPane = new JSplitPane(); browseVisualizeTabPane = new JTabbedPane(); - accountsBrowser = new AccountsBrowser(relationshipBrowser); - vizPanel = new VisualizationPanel(relationshipBrowser); setLayout(new BorderLayout()); @@ -131,10 +130,6 @@ public final class CVTTopComponent extends TopComponent { filterTabbedPaneMouseClicked(evt); } }); - - filterTabPanel.setLayout(new BorderLayout()); - filterTabPanel.add(filtersPane, BorderLayout.CENTER); - filterTabbedPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.filterTabPanel.TabConstraints.tabTitle"), filterTabPanel); // NOI18N add(filterTabbedPane, BorderLayout.WEST); @@ -143,9 +138,6 @@ public final class CVTTopComponent extends TopComponent { splitPane.setResizeWeight(0.25); browseVisualizeTabPane.setFont(new Font("Tahoma", 0, 18)); // NOI18N - browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/table.png")), accountsBrowser); // NOI18N - browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.vizPanel.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/emblem-web.png")), vizPanel); // NOI18N - splitPane.setLeftComponent(browseVisualizeTabPane); browseVisualizeTabPane.getAccessibleContext().setAccessibleName(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.browseVisualizeTabPane.AccessibleContext.accessibleName")); // NOI18N @@ -154,8 +146,8 @@ public final class CVTTopComponent extends TopComponent { private void filterTabbedPaneMouseClicked(MouseEvent evt) {//GEN-FIRST:event_filterTabPaneMouseClicked int index = filterTabbedPane.indexAtLocation(evt.getX(), evt.getY()); - if(index != -1) { - if(filtersVisible) { + if (index != -1) { + if (filtersVisible) { filterTabbedPane.setIconAt(0, new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-right.png"))); filterTabPanel.removeAll(); filterTabPanel.revalidate(); @@ -171,13 +163,10 @@ public final class CVTTopComponent extends TopComponent { // Variables declaration - do not modify//GEN-BEGIN:variables - private AccountsBrowser accountsBrowser; private JTabbedPane browseVisualizeTabPane; - private JTabbedPane filterTabbedPane; private JPanel filterTabPanel; - private FiltersPanel filtersPane; + private JTabbedPane filterTabbedPane; private JSplitPane splitPane; - private VisualizationPanel vizPanel; // End of variables declaration//GEN-END:variables @Override From 615472de900c8ca794b9a0462966d983d0e46f41 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Mar 2020 15:43:06 -0500 Subject: [PATCH 55/77] 6090 - finish fixing CVTTopComponent --- .../sleuthkit/autopsy/communications/CVTTopComponent.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java index c43e28155a..1e2755717f 100644 --- a/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java +++ b/Core/src/org/sleuthkit/autopsy/communications/CVTTopComponent.java @@ -87,6 +87,10 @@ public final class CVTTopComponent extends TopComponent { relationshipBrowser.setSelectionInfo(new SelectionInfo(new HashSet<>(), new HashSet<>(), currentFilter)); }); + filterTabPanel.setLayout(new BorderLayout()); + filterTabPanel.add(filtersPane, BorderLayout.CENTER); + browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.accountsBrowser.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/table.png")), accountsBrowser); // NOI18N + browseVisualizeTabPane.addTab(NbBundle.getMessage(CVTTopComponent.class, "CVTTopComponent.vizPanel.TabConstraints.tabTitle_1"), new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/emblem-web.png")), vizPanel); // NOI18N /* * Connect the filtersPane to the accountsBrowser and visualizaionPanel * via an Eventbus @@ -98,6 +102,7 @@ public final class CVTTopComponent extends TopComponent { filterTabbedPane.setIconAt(0, new ImageIcon(getClass().getResource("/org/sleuthkit/autopsy/communications/images/arrow-left.png"))); filterTabbedPane.setTitleAt(0, ""); + } @Subscribe From d9c072103333c2ed3f4ee7615100b81b9d33e0d6 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Tue, 3 Mar 2020 18:31:25 -0500 Subject: [PATCH 56/77] 6076 api changes to introduce summary object --- .../autopsy/filequery/FileSearch.java | 13 ++-- .../autopsy/filequery/ResultsPanel.java | 7 +- .../textsummarizer/TextSummarizer.java | 4 +- .../autopsy/textsummarizer/TextSummary.java | 76 +++++++++++++++++++ 4 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index ee5c36c8e3..87ef6bfb38 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -78,6 +78,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; import org.sleuthkit.autopsy.textextractors.TextExtractor; import org.sleuthkit.autopsy.textextractors.TextExtractorFactory; import org.sleuthkit.autopsy.textsummarizer.TextSummarizer; +import org.sleuthkit.autopsy.textsummarizer.TextSummary; /** * Main class to perform the file search. @@ -258,8 +259,8 @@ class FileSearch { */ @NbBundle.Messages({"FileSearch.documentSummary.noPreview=No preview available.", "FileSearch.documentSummary.noBytes=No bytes read for document, unable to display preview."}) - static String summarize(AbstractFile file) { - String summary = null; + static TextSummary summarize(AbstractFile file) { + TextSummary summary = null; TextSummarizer localSummarizer = summarizerToUse; if (localSummarizer == null) { synchronized (searchCache) { @@ -273,12 +274,12 @@ class FileSearch { //a summary of length 40 seems to fit without vertical scroll bars summary = localSummarizer.summarize(file, 40); } catch (IOException ex) { - return Bundle.FileSearch_documentSummary_noPreview(); + return new TextSummary(Bundle.FileSearch_documentSummary_noPreview(), null); } } - if (StringUtils.isBlank(summary)) { - //no summarizer was found or summary was empty just grab the beginning of the file - summary = getFirstLines(file); + if (summary == null || StringUtils.isBlank(summary.getSummaryText())) { + //summary text was empty grab the beginning of the file + summary = new TextSummary(getFirstLines(file), null); } return summary; } diff --git a/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java index 4711303123..bd84ba7eb1 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java @@ -55,6 +55,7 @@ import org.sleuthkit.autopsy.modules.hashdatabase.AddContentToHashDbAction; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository; +import org.sleuthkit.autopsy.textsummarizer.TextSummary; /** * Panel for displaying of file discovery results and handling the paging of @@ -777,11 +778,11 @@ public class ResultsPanel extends javax.swing.JPanel { @Messages({"ResultsPanel.unableToCreate.text=Unable to create summary."}) @Override protected Void doInBackground() throws Exception { - String preview = FileSearch.summarize(documentWrapper.getResultFile().getFirstInstance()); + TextSummary preview = FileSearch.summarize(documentWrapper.getResultFile().getFirstInstance()); if (preview == null) { - preview = Bundle.ResultsPanel_unableToCreate_text(); + preview = new TextSummary(Bundle.ResultsPanel_unableToCreate_text(), null); } - documentWrapper.setPreview(preview); + documentWrapper.setPreview(preview.getSummaryText()); return null; } diff --git a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummarizer.java b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummarizer.java index 2d40d7af5b..733ad5e517 100644 --- a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummarizer.java +++ b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummarizer.java @@ -40,9 +40,9 @@ public interface TextSummarizer { * @param file The AbstractFile to summarize. * @param summarySize The size of the summary to create. * - * @return The summary as a string. + * @return The summary as a TextSummary object. * * @throws IOException */ - String summarize(AbstractFile file, int summarySize) throws IOException; + TextSummary summarize(AbstractFile file, int summarySize) throws IOException; } diff --git a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java new file mode 100644 index 0000000000..38b4c73342 --- /dev/null +++ b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java @@ -0,0 +1,76 @@ +/* + * Autopsy + * + * Copyright 2020 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.textsummarizer; + +import java.awt.Image; +import java.util.List; + +/** + * Class to contain all information necessary to display a summary for a file.s + */ +public class TextSummary { + + private final String summaryText; + private final Image sampleImage; + private final int numberOfImages; + + /** + * Create a new TextSummary object. + * + * @param summary - The text portion of the summary. + * @param images - The Image portion of the summary + */ + public TextSummary(String summary, List images) { + summaryText = summary; + if (images == null || images.isEmpty()) { + sampleImage = null; + numberOfImages = 0; + } else { + sampleImage = selectSummaryImage(images); + numberOfImages = images.size(); + } + } + + /** + * Get the Image from the available images to include as part of the + * summary. + * + * @param images - The list of Images available to choose from. + * + * @return The selected image to include in the summary. + */ + private Image selectSummaryImage(List images) { + return images.get(0); + } + + /** + * @return the summaryText + */ + public String getSummaryText() { + return summaryText; + } + + /** + * @return the sampleImage + */ + public Image getSampleImage() { + return sampleImage; + } + +} From b9d80b753afa6e4c6832d3022680b2772e9aa173 Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Wed, 4 Mar 2020 09:27:40 -0500 Subject: [PATCH 57/77] Updated messages about regexp syntax --- .../src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties | 2 +- .../sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED | 2 +- docs/doxygen-user/keyword_search.dox | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties index 06e35314ce..21cd0d02b2 100644 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties @@ -43,7 +43,7 @@ KeywordSearchEditListPanel.keywordsLabel.text=Keywords: OpenIDE-Module-Short-Description=Keyword Search ingest module, extracted text viewer and keyword search tools KeywordSearchListsViewerPanel.manageListsButton.toolTipText=Manage keyword lists, their settings and associated keywords. The settings are shared among all cases. AbstractKeywordSearchPerformer.search.dialogErrorHeader=Keyword Search Error -AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=Invalid query syntax. If this is a regular expression search note that Java predefined and POSIX character classes are not supported. +AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=Invalid query statement. If this is a regular expression, only Lucene regular expression patterns are supported. POSIX character classes (such as \\n or \\w) are not. AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle=Keyword Search Ingest in Progress AbstractKeywordSearchPerformer.search.ingestInProgressBody=Keyword Search Ingest is currently running.
Not all files have been indexed and this search might yield incomplete results.
Do you want to proceed with this search anyway? AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody=Keyword list is empty, please add at least one keyword to the list diff --git a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED index d2fe0dd2db..27263e03ca 100755 --- a/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED +++ b/KeywordSearch/src/org/sleuthkit/autopsy/keywordsearch/Bundle.properties-MERGED @@ -79,7 +79,7 @@ KeywordSearchEditListPanel.keywordsLabel.text=Keywords: OpenIDE-Module-Short-Description=Keyword Search ingest module, extracted text viewer and keyword search tools KeywordSearchListsViewerPanel.manageListsButton.toolTipText=Manage keyword lists, their settings and associated keywords. The settings are shared among all cases. AbstractKeywordSearchPerformer.search.dialogErrorHeader=Keyword Search Error -AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=Invalid query syntax. If this is a regular expression search note that Java predefined and POSIX character classes are not supported. +AbstractKeywordSearchPerformer.search.invalidSyntaxHeader=Invalid query statement. If this is a regular expression, only Lucene regular expression patterns are supported. POSIX character classes (such as \\n or \\w) are not. AbstractKeywordSearchPerformer.search.searchIngestInProgressTitle=Keyword Search Ingest in Progress AbstractKeywordSearchPerformer.search.ingestInProgressBody=Keyword Search Ingest is currently running.
Not all files have been indexed and this search might yield incomplete results.
Do you want to proceed with this search anyway? AbstractKeywordSearchPerformer.search.emptyKeywordErrorBody=Keyword list is empty, please add at least one keyword to the list diff --git a/docs/doxygen-user/keyword_search.dox b/docs/doxygen-user/keyword_search.dox index 32163ecb48..0625459cf3 100644 --- a/docs/doxygen-user/keyword_search.dox +++ b/docs/doxygen-user/keyword_search.dox @@ -8,7 +8,9 @@ Autopsy tries its best to extract the maximum amount of text from the files bein Autopsy ships with some built-in lists that define regular expressions and enable the user to search for Phone Numbers, IP addresses, URLs and E-mail addresses. However, enabling some of these very general lists can produce a very large number of hits, and many of them can be false-positives. Regular expressions can potentially take a long time to complete. -Once files are placed in the Solr index, they can be searched quickly for specific keywords, regular expressions, or keyword search lists that can contain a mixture of keywords and regular expressions. Search queries can be executed automatically during the ingest run or at the end of the ingest, depending on the current settings and the time it takes to ingest the image. +Once files are placed in the Solr index, they can be searched quickly for specific keywords, regular expressions, or keyword search lists that can contain a mixture of keywords and regular expressions. Search queries can be executed automatically during the ingest run or at the end of the ingest, depending on the current settings and the time it takes to ingest the image. + +Refer to \ref ad_hoc_keyword_search_page for more details on specifying regular expressions and other types of searches. \section keyword_search_configuration_dialog Keyword Search Configuration Dialog From 720980422a031f646281778bb706ef90beee310f Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 4 Mar 2020 10:30:42 -0500 Subject: [PATCH 58/77] 6100: Suppress creation of Persona tables. --- .../datamodel/RdbmsCentralRepoFactory.java | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index 2fa248598e..db7343ad50 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -134,7 +134,7 @@ public class RdbmsCentralRepoFactory { stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMajor() + "')"); stmt.execute("INSERT INTO db_info (name, value) VALUES ('" + RdbmsCentralRepo.CREATION_SCHEMA_MINOR_VERSION_KEY + "', '" + SOFTWARE_CR_DB_SCHEMA_VERSION.getMinor() + "')"); - // Create account_types and accounts tab;es which are referred by X_instances tables + // Create account_types and accounts tables which are referred by X_instances tables stmt.execute(getCreateAccountTypesTableStatement(selectedPlatform)); stmt.execute(getCreateAccountsTableStatement(selectedPlatform)); @@ -161,7 +161,8 @@ public class RdbmsCentralRepoFactory { stmt.execute(String.format(getReferenceTypeValueKnownstatusIndexTemplate(), reference_type_dbname, reference_type_dbname)); } } - createPersonaTables(stmt); + // @TODO: uncomment this when ready to create Persona tables. + //createPersonaTables(stmt); } catch (SQLException ex) { LOGGER.log(Level.SEVERE, "Error initializing db schema.", ex); // NON-NLS return false; @@ -191,8 +192,9 @@ public class RdbmsCentralRepoFactory { } result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) - && CentralRepoDbUtil.insertDefaultOrganization(conn) - && insertDefaultPersonaTablesContent(conn); + && CentralRepoDbUtil.insertDefaultOrganization(conn); + // @TODO: uncomment when ready to create/populate persona tables + // && insertDefaultPersonaTablesContent(conn); } catch (SQLException ex) { LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in CR tables."), ex); @@ -576,7 +578,6 @@ public class RdbmsCentralRepoFactory { stmt.execute(getCreateConfidenceTableStatement(selectedPlatform)); stmt.execute(getCreateExaminersTableStatement(selectedPlatform)); stmt.execute(getCreatePersonaStatusTableStatement(selectedPlatform)); - stmt.execute(getCreateAliasesTableStatement(selectedPlatform)); stmt.execute(getCreatePersonasTableStatement(selectedPlatform)); stmt.execute(getCreatePersonaAliasTableStatement(selectedPlatform)); @@ -653,20 +654,6 @@ public class RdbmsCentralRepoFactory { + ")"; } - /** - * Get the SQL String for creating a new aliases table in a central - * repository. - * - * @return SQL string for creating aliases table - */ - static String getCreateAliasesTableStatement(CentralRepoPlatforms selectedPlatform) { - - return "CREATE TABLE IF NOT EXISTS aliases (" - + getNumericPrimaryKeyClause("id", selectedPlatform) - + "alias TEXT NOT NULL," - + "CONSTRAINT alias_unique UNIQUE(alias)" - + ")"; - } /** * Get the SQL String for creating a new accounts table in a central @@ -719,13 +706,12 @@ public class RdbmsCentralRepoFactory { return "CREATE TABLE IF NOT EXISTS persona_alias (" + getNumericPrimaryKeyClause("id", selectedPlatform) + "persona_id " + getBigIntType(selectedPlatform) + " ," - + "alias_id " + getBigIntType(selectedPlatform) + " ," + + "alias TEXT NOT NULL, " + "justification TEXT NOT NULL," + "confidence_id integer NOT NULL," + "date_added " + getBigIntType(selectedPlatform) + " ," + "examiner_id integer NOT NULL," + "FOREIGN KEY (persona_id) REFERENCES personas(id)," - + "FOREIGN KEY (alias_id) REFERENCES aliases(id)," + "FOREIGN KEY (confidence_id) REFERENCES confidence(confidence_id)," + "FOREIGN KEY (examiner_id) REFERENCES examiners(id)" + ")"; From 516c1575d678c18dda5547d98ef2fee8697627f1 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 4 Mar 2020 13:35:19 -0500 Subject: [PATCH 59/77] 6076 textsummarizer api changes --- .../autopsy/filequery/FileSearch.java | 4 +-- .../autopsy/filequery/ResultsPanel.java | 2 +- .../autopsy/textsummarizer/TextSummary.java | 29 +++++-------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index 87ef6bfb38..00ff3c083c 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -274,12 +274,12 @@ class FileSearch { //a summary of length 40 seems to fit without vertical scroll bars summary = localSummarizer.summarize(file, 40); } catch (IOException ex) { - return new TextSummary(Bundle.FileSearch_documentSummary_noPreview(), null); + return new TextSummary(Bundle.FileSearch_documentSummary_noPreview(), null, 0); } } if (summary == null || StringUtils.isBlank(summary.getSummaryText())) { //summary text was empty grab the beginning of the file - summary = new TextSummary(getFirstLines(file), null); + summary = new TextSummary(getFirstLines(file), null, 0); } return summary; } diff --git a/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java b/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java index bd84ba7eb1..7ba0e452ca 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/ResultsPanel.java @@ -780,7 +780,7 @@ public class ResultsPanel extends javax.swing.JPanel { protected Void doInBackground() throws Exception { TextSummary preview = FileSearch.summarize(documentWrapper.getResultFile().getFirstInstance()); if (preview == null) { - preview = new TextSummary(Bundle.ResultsPanel_unableToCreate_text(), null); + preview = new TextSummary(Bundle.ResultsPanel_unableToCreate_text(), null, 0); } documentWrapper.setPreview(preview.getSummaryText()); return null; diff --git a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java index 38b4c73342..c556f98b14 100644 --- a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java +++ b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java @@ -33,30 +33,15 @@ public class TextSummary { /** * Create a new TextSummary object. * - * @param summary - The text portion of the summary. - * @param images - The Image portion of the summary + * @param summary - The text portion of the summary. + * @param image - The Image portion of the summary + * @param countOfImages - The number of images including the one provided in + * the document. */ - public TextSummary(String summary, List images) { + public TextSummary(String summary, Image image, int countOfImages) { summaryText = summary; - if (images == null || images.isEmpty()) { - sampleImage = null; - numberOfImages = 0; - } else { - sampleImage = selectSummaryImage(images); - numberOfImages = images.size(); - } - } - - /** - * Get the Image from the available images to include as part of the - * summary. - * - * @param images - The list of Images available to choose from. - * - * @return The selected image to include in the summary. - */ - private Image selectSummaryImage(List images) { - return images.get(0); + sampleImage = image; + numberOfImages = countOfImages; } /** From 1dd59dc16d0de1968ae3c2ff35226337b45b6e68 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 4 Mar 2020 13:41:03 -0500 Subject: [PATCH 60/77] 6076 add method to get number of images from summary --- .../org/sleuthkit/autopsy/textsummarizer/TextSummary.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java index c556f98b14..27c10d4fcc 100644 --- a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java +++ b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java @@ -58,4 +58,11 @@ public class TextSummary { return sampleImage; } + /** + * @return the numberOfImages + */ + int getNumberOfImages() { + return numberOfImages; + } + } From e9dd8b1b008c99cc1e57282b3c0eafac0102f795 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 4 Mar 2020 13:41:52 -0500 Subject: [PATCH 61/77] 6076 add method to get number of images from summary --- Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java index 27c10d4fcc..04eb201580 100644 --- a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java +++ b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java @@ -61,7 +61,7 @@ public class TextSummary { /** * @return the numberOfImages */ - int getNumberOfImages() { + public int getNumberOfImages() { return numberOfImages; } From 2a84b8e596e598d5710aba80f4a0b05ac4bafa87 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Wed, 4 Mar 2020 13:45:52 -0500 Subject: [PATCH 62/77] 6076 remove unused import --- Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java index 04eb201580..86d6122188 100644 --- a/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java +++ b/Core/src/org/sleuthkit/autopsy/textsummarizer/TextSummary.java @@ -19,7 +19,6 @@ package org.sleuthkit.autopsy.textsummarizer; import java.awt.Image; -import java.util.List; /** * Class to contain all information necessary to display a summary for a file.s From 294aa6c7730e8ca32fac93119127377f0841f376 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Wed, 4 Mar 2020 14:44:55 -0500 Subject: [PATCH 63/77] Ensure default content gets populated in Accounts related tables. --- .../datamodel/RdbmsCentralRepoFactory.java | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index db7343ad50..09f103a038 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -192,7 +192,8 @@ public class RdbmsCentralRepoFactory { } result = CentralRepoDbUtil.insertDefaultCorrelationTypes(conn) - && CentralRepoDbUtil.insertDefaultOrganization(conn); + && CentralRepoDbUtil.insertDefaultOrganization(conn) && + insertDefaultAccountsTablesContent(conn); // @TODO: uncomment when ready to create/populate persona tables // && insertDefaultPersonaTablesContent(conn); @@ -765,6 +766,43 @@ public class RdbmsCentralRepoFactory { } + /** + * Inserts the default content in accounts related tables. + * + * @param conn Database connection to use. + * + * @return True if success, false otherwise. + */ + private boolean insertDefaultAccountsTablesContent(Connection conn) { + Statement stmt = null; + try { + stmt = conn.createStatement(); + + // Populate the account_types table + for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { + int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type); + if (correlationTypeId > 0) { + String sqlString = String.format("INSERT INTO account_types (type_name, display_name, correlation_type_id) VALUES ('%s', '%s', %d)" + getOnConflictDoNothingClause(selectedPlatform), + type.getTypeName(), type.getDisplayName(), correlationTypeId); + stmt.execute(sqlString); + } + } + } catch (SQLException ex) { + LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in Accounts tables."), ex); + return false; + } finally { + if (stmt != null) { + try { + stmt.close(); + } catch (SQLException ex2) { + LOGGER.log(Level.SEVERE, "Error closing statement.", ex2); + } + } + } + + return true; + } + /** * Inserts the default content in persona related tables. * @@ -792,16 +830,6 @@ public class RdbmsCentralRepoFactory { stmt.execute(sqlString); } - // Populate the account_types table - for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { - int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type); - if (correlationTypeId > 0) { - String sqlString = String.format("INSERT INTO account_types (type_name, display_name, correlation_type_id) VALUES ('%s', '%s', %d)" + getOnConflictDoNothingClause(selectedPlatform), - type.getTypeName(), type.getDisplayName(), correlationTypeId); - stmt.execute(sqlString); - } - } - } catch (SQLException ex) { LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in Persona tables."), ex); return false; From 08bd00734dadcd87b23d76fd1cc5a0ec29ca90fe Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Wed, 4 Mar 2020 16:21:40 -0500 Subject: [PATCH 64/77] Updated based on review comments --- .../org/sleuthkit/autopsy/geolocation/datamodel/Route.java | 2 +- .../org/sleuthkit/autopsy/geolocation/datamodel/Track.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index cda71c0e60..67de1e55ba 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -43,7 +43,7 @@ public class Route extends GeoPath { // constructor will take care of creating an unmodifiable List private final List propertiesList; - private static final TskGeoWaypointsUtil attributeUtil = new TskGeoWaypointsUtil(""); + private static final TskGeoWaypointsUtil attributeUtil = new TskGeoWaypointsUtil(); /** * Construct a route for the given artifact. diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java index 3760c6f1eb..1a816179f6 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java @@ -38,7 +38,7 @@ public final class Track extends GeoPath{ private final Long startTimestamp; private final Long endTimeStamp; - private static final TskGeoTrackpointsUtil attributeUtil = new TskGeoTrackpointsUtil(""); + private static final TskGeoTrackpointsUtil attributeUtil = new TskGeoTrackpointsUtil(); /** * Construct a new Track for the given artifact. @@ -204,7 +204,7 @@ public final class Track extends GeoPath{ list.add(new Property(Bundle.Track_distanceTraveled_displayName(), value.toString())); } - value = point.getDistanceFromHP(); + value = point.getDistanceFromHomePoint(); if (value != null) { list.add(new Property(Bundle.Track_distanceFromHome_displayName(), value.toString())); } From 82806cec8ea94f2e2bc0485dc95345bf65eec1b0 Mon Sep 17 00:00:00 2001 From: "U-BASIS\\dsmyda" Date: Wed, 4 Mar 2020 17:48:59 -0500 Subject: [PATCH 65/77] Removed the disabled ios module from develop --- .../autopsy/modules/iOS/Bundle.properties | 5 - .../modules/iOS/Bundle.properties-MERGED | 8 - .../autopsy/modules/iOS/Bundle_ja.properties | 8 - .../autopsy/modules/iOS/CallLogAnalyzer.java | 192 -------------- .../autopsy/modules/iOS/ContactAnalyzer.java | 251 ------------------ .../modules/iOS/TextMessageAnalyzer.java | 198 -------------- .../autopsy/modules/iOS/iOSIngestModule.java | 50 ---- .../autopsy/modules/iOS/iOSModuleFactory.java | 59 ---- 8 files changed, 771 deletions(-) delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties delete mode 100755 Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties-MERGED delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle_ja.properties delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java delete mode 100644 Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties deleted file mode 100644 index 8909d23e0e..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties +++ /dev/null @@ -1,5 +0,0 @@ -iOSModuleFactory.moduleName=iOS Analyzer -iOSModuleFactory.moduleDescription=Extracts system and 3rd party app data -TextMessageAnalyzer.bbAttribute.incoming=Incoming -TextMessageAnalyzer.bbAttribute.outgoing=Outgoing -TextMessageAnalyzer.bbAttribute.smsMessage=SMS Message diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties-MERGED deleted file mode 100755 index 33c0a3ed08..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle.properties-MERGED +++ /dev/null @@ -1,8 +0,0 @@ -CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search. -ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search. -iOSModuleFactory.moduleName=iOS Analyzer -iOSModuleFactory.moduleDescription=Extracts system and 3rd party app data -TextMessageAnalyzer.bbAttribute.incoming=Incoming -TextMessageAnalyzer.bbAttribute.outgoing=Outgoing -TextMessageAnalyzer.bbAttribute.smsMessage=SMS Message -TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search. diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle_ja.properties b/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle_ja.properties deleted file mode 100644 index 03cd3cc41e..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/Bundle_ja.properties +++ /dev/null @@ -1,8 +0,0 @@ -CallLogAnalyzer.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u691c\u7d22\u3059\u308b\u305f\u3081\u306e\u3001\u901a\u8a71\u30ed\u30b0\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -ContactAnalyzer.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u691c\u7d22\u3059\u308b\u305f\u3081\u306e\u3001\u9023\u7d61\u5148\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 -iOSModuleFactory.moduleName=iOS Analyzer -iOSModuleFactory.moduleDescription=\u30b7\u30b9\u30c6\u30e0\u3068\u30b5\u30fc\u30c9\u30d1\u30fc\u30c6\u30a3\u88fd\u30a2\u30d7\u30ea\u30c7\u30fc\u30bf\u3092\u62bd\u51fa -TextMessageAnalyzer.bbAttribute.incoming=\u53d7\u4fe1 -TextMessageAnalyzer.bbAttribute.outgoing=\u9001\u4fe1 -TextMessageAnalyzer.bbAttribute.smsMessage=SMS\u30e1\u30c3\u30bb\u30fc\u30b8 -TextMessageAnalyzer.indexError.message=\u30ad\u30fc\u30ef\u30fc\u30c9\u3092\u691c\u7d22\u3059\u308b\u305f\u3081\u306e\u3001\u30c6\u30ad\u30b9\u30c8\u30e1\u30c3\u30bb\u30fc\u30b8\u30a2\u30fc\u30c6\u30a3\u30d5\u30a1\u30af\u30c8\u3092\u30a4\u30f3\u30c7\u30c3\u30af\u30b9\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f\u3002 diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java deleted file mode 100644 index 908673f466..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/CallLogAnalyzer.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014-2018 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.iOS; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Blackboard; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Look for call logs and allow resulting blackboard artifacts to be generated. - */ -final class CallLogAnalyzer { - - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private long fileId = 0; - private java.io.File jFile = null; - private final String moduleName = iOSModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName()); - private Blackboard blackboard; - - /** - * Find call logs given an ingest job context and index the results. - * - * @param context The ingest job context. - */ - public void findCallLogs(IngestJobContext context) { - Case openCase; - try { - openCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return; - } - blackboard = openCase.getSleuthkitCase().getBlackboard(); - List absFiles; - try { - SleuthkitCase skCase = openCase.getSleuthkitCase(); - absFiles = skCase.findAllFilesWhere("name ='contacts2.db' OR name ='contacts.db'"); //NON-NLS //get exact file names - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile file : absFiles) { - String dbPath = ""; - try { - jFile = new java.io.File(Case.getCurrentCaseThrows().getTempDirectory(), file.getName().replaceAll("[<>%|\"/:*\\\\]", "")); - dbPath = jFile.toString(); //path of file as string - fileId = file.getId(); - ContentUtils.writeToFile(file, jFile, context::dataSourceIngestIsCancelled); - findCallLogsInDB(dbPath, fileId); - } catch (ReadContentInputStreamException ex) { - logger.log(Level.WARNING, String.format("Error reading content from file '%s' (id=%d).", file.getName(), fileId), ex); //NON-NLS - } catch (Exception ex) { - logger.log(Level.SEVERE, String.format("Error writing content from file '%s' (id=%d) to '%s'.", file.getName(), fileId, dbPath), ex); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Call logs", e); //NON-NLS - } - } - - /** - * Index results for call logs found in the database. - * - * @param DatabasePath The path to the database. - * @param fileId The ID of the file associated with artifacts. - */ - @Messages({"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."}) - private void findCallLogsInDB(String DatabasePath, long fileId) { - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - } - - Case currentCase; - try { - currentCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return; - } - SleuthkitCase skCase = currentCase.getSleuthkitCase(); - try { - AbstractFile file = skCase.getAbstractFileById(fileId); - if (file == null) { - logger.log(Level.SEVERE, "Error getting abstract file {0}", fileId); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT number,date,duration,type, name FROM calls ORDER BY date DESC;"); //NON-NLS - - BlackboardArtifact bba; - String name; // name of person dialed or called. null if unregistered - String number; //string phone number - String duration; //duration of call in seconds - String date; // Unix time - String type; // 1 incoming, 2 outgoing, 3 missed - - while (resultSet.next()) { - name = resultSet.getString("name"); //NON-NLS - number = resultSet.getString("number"); //NON-NLS - duration = resultSet.getString("duration"); //NON-NLS - date = resultSet.getString("date"); //NON-NLS - type = resultSet.getString("type"); //NON-NLS - - bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); //create a call log and then add attributes from result set. - Collection attributes = new ArrayList<>(); - if (type.equalsIgnoreCase("outgoing")) { //NON-NLS - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, number)); - } else { /// Covers INCOMING and MISSED - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, number)); - } - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, date)); // RC: Should be long! - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, duration + date)); // RC: Should be long! - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, type)); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - - bba.addAttributes(attributes); - try { - /* - * post the artifact which will index the artifact for - * keyword search, and fire an event to notify UI of - * this new artifact - */ - blackboard.postArtifact(bba, moduleName); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); //NON-NLS - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing the database", e); //NON-NLS - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Call logs to the Blackboard", e); //NON-NLS - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java deleted file mode 100644 index cde321fab4..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/ContactAnalyzer.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014-2019 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.iOS; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Blackboard; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.ReadContentInputStream; -import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Look for call logs and allow resulting blackboard artifacts to be generated. - */ -final class ContactAnalyzer { - - private Connection connection = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - private final String moduleName = iOSModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName()); - private Blackboard blackboard; - - /** - * Find contacts given an ingest job context and index the results. - * - * @param context The ingest job context. - */ - public void findContacts(IngestJobContext context) { - Case openCase; - try { - openCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return; - } - - blackboard = openCase.getSleuthkitCase().getBlackboard(); - List absFiles; - try { - SleuthkitCase skCase = openCase.getSleuthkitCase(); - absFiles = skCase.findAllFilesWhere("LOWER(name) LIKE LOWER('%call_history%') "); //NON-NLS //get exact file names - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile file : absFiles) { - try { - jFile = new java.io.File(openCase.getTempDirectory(), file.getName().replaceAll("[<>%|\"/:*\\\\]", "")); - dbPath = jFile.toString(); //path of file as string - fileId = file.getId(); - ContentUtils.writeToFile(file, jFile, context::dataSourceIngestIsCancelled); - } catch (ReadContentInputStreamException ex) { - logger.log(Level.WARNING, String.format("Error reading content from file '%s' (id=%d).", file.getName(), fileId), ex); //NON-NLS - } catch (Exception ex) { - logger.log(Level.SEVERE, String.format("Error writing content from file '%s' (id=%d) to '%s'.", file.getName(), fileId, dbPath), ex); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding Contacts", e); //NON-NLS - } - } - - /** - * Create blackboard artifacts and index results for call logs found in the - * database. - * - * @param DatabasePath The path to the database. - * @param fileId The ID of the file associated with artifacts. - */ - @Messages({"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."}) - private void findContactsInDB(String DatabasePath, long fileId) { - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - - Case currentCase; - try { - currentCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return; - } - - Statement statement = null; - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - } - - SleuthkitCase skCase = currentCase.getSleuthkitCase(); - try { - AbstractFile file = skCase.getAbstractFileById(fileId); - if (file == null) { - logger.log(Level.SEVERE, "Error getting abstract file {0}", fileId); //NON-NLS - return; - } - - ResultSet resultSet = null; - try { - // get display_name, mimetype(email or phone number) and data1 (phonenumber or email address depending on mimetype) - //sorted by name, so phonenumber/email would be consecutive for a person if they exist. - resultSet = statement.executeQuery( - "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n" //NON-NLS - + "FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n" //NON-NLS - + "JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) " //NON-NLS - + "LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n" //NON-NLS - + "LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n" //NON-NLS - + "WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n" //NON-NLS - + "ORDER BY name_raw_contact.display_name ASC;"); //NON-NLS - - BlackboardArtifact bba; - bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - Collection attributes = new ArrayList<>(); - String name; - String oldName = ""; - String mimetype; // either phone or email - String data1; // the phone number or email - while (resultSet.next()) { - name = resultSet.getString("display_name"); //NON-NLS - data1 = resultSet.getString("data1"); //NON-NLS - mimetype = resultSet.getString("mimetype"); //NON-NLS - if (name.equals(oldName) == false) { - bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT); - attributes = new ArrayList<>(); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name)); - } - if (mimetype.equals("vnd.android.cursor.item/phone_v2")) { //NON-NLS - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, data1)); - } else { - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1)); - } - - // TODO: If this code comes back to life, add code to create the account - // and relationship between the phone numbers & emails. Also - // investigate if the mimetype "vnd.android.cursor.item/phone_v2" - // makes sense in an ios word - - oldName = name; - - bba.addAttributes(attributes); - try { - // index the artifact for keyword search - blackboard.postArtifact(bba, moduleName); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); //NON-NLS - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing Contacts to Blackboard", e); //NON-NLS - } - - } - - public static void copyFileUsingStream(AbstractFile file, File jFile) throws IOException { - InputStream is = new ReadContentInputStream(file); - OutputStream os = new FileOutputStream(jFile); - byte[] buffer = new byte[8192]; - int length; - try { - while ((length = is.read(buffer)) != -1) { - os.write(buffer, 0, length); - os.flush(); - - } - - } finally { - is.close(); - os.close(); - } - } - - public static void copyFileUsingStreams(AbstractFile file, File jFile) { - InputStream istream; - OutputStream ostream = null; - int c; - final int EOF = -1; - istream = new ReadContentInputStream(file); - try { - ostream = new FileOutputStream(jFile); - while ((c = istream.read()) != EOF) { - ostream.write(c); - } - } catch (IOException e) { - logger.log(Level.WARNING, "Error copying file", e); - } finally { - try { - istream.close(); - ostream.close(); - } catch (IOException e) { - logger.log(Level.WARNING, "File did not close", e); - } - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java deleted file mode 100644 index c541bf608a..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/TextMessageAnalyzer.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014-2018 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.iOS; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.logging.Level; -import org.openide.util.NbBundle; -import org.openide.util.NbBundle.Messages; -import org.sleuthkit.autopsy.casemodule.Case; -import org.sleuthkit.autopsy.casemodule.NoCurrentCaseException; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; -import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.Blackboard; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; -import org.sleuthkit.datamodel.ReadContentInputStream; -import org.sleuthkit.datamodel.SleuthkitCase; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * Look for text messages and allow resulting blackboard artifacts to be - * generated. - */ -class TextMessageAnalyzer { - - private Connection connection = null; - private ResultSet resultSet = null; - private Statement statement = null; - private String dbPath = ""; - private long fileId = 0; - private java.io.File jFile = null; - List absFiles; - private final String moduleName = iOSModuleFactory.getModuleName(); - private static final Logger logger = Logger.getLogger(TextMessageAnalyzer.class.getName()); - private Blackboard blackboard; - - /** - * Find text messages given an ingest job context and index the results. - * - * @param context The ingest job context. - */ - void findTexts(IngestJobContext context) { - Case openCase; - try { - openCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return; - } - blackboard = openCase.getSleuthkitCase().getBlackboard(); - try { - SleuthkitCase skCase = openCase.getSleuthkitCase(); - absFiles = skCase.findAllFilesWhere("name ='mmssms.db'"); //NON-NLS //get exact file name - if (absFiles.isEmpty()) { - return; - } - for (AbstractFile file : absFiles) { - try { - jFile = new java.io.File(Case.getCurrentCaseThrows().getTempDirectory(), file.getName().replaceAll("[<>%|\"/:*\\\\]", "")); - dbPath = jFile.toString(); //path of file as string - fileId = file.getId(); - ContentUtils.writeToFile(file, jFile, context::dataSourceIngestIsCancelled); - findTextsInDB(dbPath, fileId); - } catch (ReadContentInputStream.ReadContentInputStreamException ex) { - logger.log(Level.WARNING, String.format("Error reading content from file '%s' (id=%d).", file.getName(), fileId), ex); //NON-NLS - } catch (Exception ex) { - logger.log(Level.SEVERE, String.format("Error writing content from file '%s' (id=%d) to '%s'.", file.getName(), fileId, dbPath), ex); //NON-NLS - } - } - } catch (TskCoreException e) { - logger.log(Level.SEVERE, "Error finding text messages", e); //NON-NLS - } - } - - /** - * Create blackboard artifacts and index results for text messages found in - * the database. - * - * @param DatabasePath The path to the database. - * @param fileId The ID of the file associated with artifacts. - */ - @Messages({"TextMessageAnalyzer.indexError.message=Failed to index text message artifact for keyword search."}) - private void findTextsInDB(String DatabasePath, long fileId) { - if (DatabasePath == null || DatabasePath.isEmpty()) { - return; - } - Case currentCase; - try { - currentCase = Case.getCurrentCaseThrows(); - } catch (NoCurrentCaseException ex) { - logger.log(Level.SEVERE, "Exception while getting open case.", ex); //NON-NLS - return; - } - try { - Class.forName("org.sqlite.JDBC"); //NON-NLS //load JDBC driver - connection = DriverManager.getConnection("jdbc:sqlite:" + DatabasePath); //NON-NLS - statement = connection.createStatement(); - } catch (ClassNotFoundException | SQLException e) { - logger.log(Level.SEVERE, "Error opening database", e); //NON-NLS - } - - SleuthkitCase skCase = currentCase.getSleuthkitCase(); - try { - AbstractFile file = skCase.getAbstractFileById(fileId); - if (file == null) { - logger.log(Level.SEVERE, "Error getting abstract file {0}", fileId); //NON-NLS - return; - } - - try { - resultSet = statement.executeQuery( - "SELECT address,date,type,subject,body FROM sms;"); //NON-NLS - - BlackboardArtifact bba; - String address; // may be phone number, or other addresses - String date;//unix time - String type; // message received in inbox = 1, message sent = 2 - String subject;//message subject - String body; //message body - while (resultSet.next()) { - address = resultSet.getString("address"); //NON-NLS - date = resultSet.getString("date"); //NON-NLS - type = resultSet.getString("type"); //NON-NLS - subject = resultSet.getString("subject"); //NON-NLS - body = resultSet.getString("body"); //NON-NLS - - bba = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_MESSAGE); //create Message artifact and then add attributes from result set. - Collection attributes = new ArrayList<>(); - // @@@ NEed to put into more specific TO or FROM - if (type.equals("1")) { - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.incoming"))); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, address)); - } else { - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.outgoing"))); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, address)); - } - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, moduleName, date)); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, type)); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SUBJECT, moduleName, subject)); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TEXT, moduleName, body)); - attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_MESSAGE_TYPE, moduleName, NbBundle.getMessage(this.getClass(), "TextMessageAnalyzer.bbAttribute.smsMessage"))); - - bba.addAttributes(attributes); - try { - /* - * post the artifact which will index the artifact for - * keyword search, and fire an event to notify UI of - * this new artifact - */ blackboard.postArtifact(bba, moduleName); - } catch (Blackboard.BlackboardException ex) { - logger.log(Level.SEVERE, "Unable to index blackboard artifact " + bba.getArtifactID(), ex); //NON-NLS - MessageNotifyUtil.Notify.error( - Bundle.TextMessageAnalyzer_indexError_message(), bba.getDisplayName()); - } - } - - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); //NON-NLS - } finally { - try { - resultSet.close(); - statement.close(); - connection.close(); - } catch (Exception e) { - logger.log(Level.SEVERE, "Error closing database", e); //NON-NLS - } - } - } catch (Exception e) { - logger.log(Level.SEVERE, "Error parsing text messages to Blackboard", e); //NON-NLS - } - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java deleted file mode 100644 index b0aacc9119..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSIngestModule.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.iOS; - -import java.util.HashMap; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModuleProgress; -import org.sleuthkit.autopsy.ingest.IngestModule; -import org.sleuthkit.datamodel.Content; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.IngestJobContext; -import org.sleuthkit.autopsy.ingest.IngestModuleReferenceCounter; -import org.sleuthkit.autopsy.ingest.IngestServices; - -class iOSIngestModule implements DataSourceIngestModule { - - private static final HashMap fileCountsForIngestJobs = new HashMap<>(); - private IngestJobContext context = null; - private static final IngestModuleReferenceCounter refCounter = new IngestModuleReferenceCounter(); - private static final Logger logger = Logger.getLogger(iOSModuleFactory.class.getName()); - private IngestServices services = IngestServices.getInstance(); - - @Override - public void startUp(IngestJobContext context) throws IngestModule.IngestModuleException { - this.context = context; - } - - @Override - public IngestModule.ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) { - ContactAnalyzer FindContacts = new ContactAnalyzer(); - FindContacts.findContacts(context); - return IngestModule.ProcessResult.OK; - } -} diff --git a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java b/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java deleted file mode 100644 index 942dca5379..0000000000 --- a/Core/src/org/sleuthkit/autopsy/modules/iOS/iOSModuleFactory.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2014 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.modules.iOS; - -import org.openide.util.NbBundle; -import org.sleuthkit.autopsy.coreutils.Version; -import org.sleuthkit.autopsy.ingest.DataSourceIngestModule; -import org.sleuthkit.autopsy.ingest.IngestModuleFactoryAdapter; -import org.sleuthkit.autopsy.ingest.IngestModuleIngestJobSettings; - -//@ServiceProvider(service = IngestModuleFactory.class) // -public class iOSModuleFactory extends IngestModuleFactoryAdapter { - - static String getModuleName() { - return NbBundle.getMessage(iOSModuleFactory.class, "iOSModuleFactory.moduleName"); - } - - @Override - public String getModuleDisplayName() { - return getModuleName(); - } - - @Override - public String getModuleDescription() { - return NbBundle.getMessage(iOSModuleFactory.class, "iOSModuleFactory.moduleDescription"); - } - - @Override - public String getModuleVersionNumber() { - return Version.getVersion(); - } - - @Override - public boolean isDataSourceIngestModuleFactory() { - return true; - } - - @Override - public DataSourceIngestModule createDataSourceIngestModule(IngestModuleIngestJobSettings settings) { - return new iOSIngestModule(); - } - -} From 22fccaf14227f641142affc50440128b352f6e28 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Wed, 4 Mar 2020 18:59:20 -0500 Subject: [PATCH 66/77] Improve enable CR message --- .../autopsy/centralrepository/eventlisteners/Installer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 54a642b0dc..208f201a30 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -58,7 +58,7 @@ public class Installer extends ModuleInstall { @NbBundle.Messages({ "Installer.initialCreateSqlite.title=Enable Central Repository?", - "Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to?", + "Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to enable it?", "Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. " + "You can use this to ignore previously seen files and make connections between cases." }) From d3089f7bf3c56d66edf4cd41ddb757f730153157 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Thu, 5 Mar 2020 09:59:21 -0500 Subject: [PATCH 67/77] Update contextviewer for source and usage Add both source and usage to contextviewer at same time. --- .../contextviewer/Bundle.properties-MERGED | 8 +- .../contextviewer/ContextViewer.form | 72 ++++++++++-- .../contextviewer/ContextViewer.java | 110 ++++++++++++++++-- 3 files changed, 169 insertions(+), 21 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED index b29e7190fd..aafa549431 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED @@ -3,16 +3,20 @@ ContextViewer.downloadedOn=On ContextViewer.downloadSource=Downloaded from: ContextViewer.downloadURL=URL ContextViewer.email=Email -ContextViewer.file=File ContextViewer.jSourceGoToResultButton.text=Go to Result ContextViewer.jSourceTextLabel.text=jLabel2 ContextViewer.jSourceNameLabel.text=jSourceNameLabel ContextViewer.jSourceLabel.text=Source +ContextViewer.jUsageGoToResultButton.text=Go to Result +ContextViewer.jUsageLabel.text=Usage +ContextViewer.jUsageNameLabel.text=jSourceNameLabel +ContextViewer.jUsageTextLabel.text=jLabel2 ContextViewer.message=Message ContextViewer.messageFrom=From ContextViewer.messageOn=On ContextViewer.messageTo=To -ContextViewer.on=On +ContextViewer.on=Opened on ContextViewer.recentDocs=Recent Documents: ContextViewer.title=Context ContextViewer.toolTip=Displays context for selected file. +ContextViewer.unknown=Opened on unknown time diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form index f7e70919c0..ab4771fc71 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form @@ -27,17 +27,30 @@ - - - - - + + + + + + + + + + + + + + + - - + + + + + @@ -56,7 +69,16 @@ - + + + + + + + + + + @@ -96,5 +118,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java index 1baa412495..0e8e03f5b1 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java @@ -83,6 +83,10 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte jSourceLabel = new javax.swing.JLabel(); jSourceNameLabel = new javax.swing.JLabel(); jSourceTextLabel = new javax.swing.JLabel(); + jUsageGoToResultButton = new javax.swing.JButton(); + jUsageLabel = new javax.swing.JLabel(); + jUsageNameLabel = new javax.swing.JLabel(); + jUsageTextLabel = new javax.swing.JLabel(); setBackground(new java.awt.Color(255, 255, 255)); @@ -100,6 +104,20 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte org.openide.awt.Mnemonics.setLocalizedText(jSourceTextLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jSourceTextLabel.text")); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jUsageGoToResultButton, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUsageGoToResultButton.text")); // NOI18N + jUsageGoToResultButton.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jUsageGoToResultButtonActionPerformed(evt); + } + }); + + jUsageLabel.setFont(new java.awt.Font("Dialog", 1, 14)); // NOI18N + org.openide.awt.Mnemonics.setLocalizedText(jUsageLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUsageLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jUsageNameLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUsageNameLabel.text")); // NOI18N + + org.openide.awt.Mnemonics.setLocalizedText(jUsageTextLabel, org.openide.util.NbBundle.getMessage(ContextViewer.class, "ContextViewer.jUsageTextLabel.text")); // NOI18N + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); this.setLayout(layout); layout.setHorizontalGroup( @@ -110,14 +128,23 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jSourceLabel) + .addComponent(jUsageLabel) .addGroup(layout.createSequentialGroup() .addGap(6, 6, 6) - .addComponent(jSourceNameLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE))) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jSourceNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jUsageNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE))))) .addGap(36, 36, 36)) .addGroup(layout.createSequentialGroup() - .addComponent(jSourceGoToResultButton) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSourceGoToResultButton) + .addComponent(jUsageGoToResultButton)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) ); layout.setVerticalGroup( @@ -131,7 +158,15 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte .addComponent(jSourceTextLabel)) .addGap(18, 18, 18) .addComponent(jSourceGoToResultButton) - .addGap(0, 203, Short.MAX_VALUE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jUsageLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jUsageNameLabel) + .addComponent(jUsageTextLabel)) + .addGap(18, 18, 18) + .addComponent(jUsageGoToResultButton) + .addGap(0, 60, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -146,6 +181,15 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte }//GEN-LAST:event_jSourceGoToResultButtonActionPerformed + private void jUsageGoToResultButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jUsageGoToResultButtonActionPerformed + final DirectoryTreeTopComponent dtc = DirectoryTreeTopComponent.findInstance(); + + // Navigate to the source context artifact. + if (sourceContextArtifact != null) { + dtc.viewArtifact(sourceContextArtifact); + } + }//GEN-LAST:event_jUsageGoToResultButtonActionPerformed + @Override public void setNode(Node selectedNode) { if ((selectedNode == null) || (!isSupported(selectedNode))) { @@ -246,9 +290,12 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte } } jSourceGoToResultButton.setVisible(true); + jUsageGoToResultButton.setVisible(true); if (foundASource == false) { setSourceName("Unknown"); showSourceText(false); + setUsageName("Unknown"); + showUsageText(false); } } @@ -263,6 +310,11 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte * @throws TskCoreException */ private void addSourceEntry(BlackboardArtifact artifact) throws TskCoreException { + setSourceName("Unknown"); + showSourceText(false); + setUsageName("Unknown"); + showUsageText(false); + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_ASSOCIATED_OBJECT.getTypeID() == artifact.getArtifactTypeID()) { BlackboardAttribute associatedArtifactAttribute = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ASSOCIATED_ARTIFACT)); if (associatedArtifactAttribute != null) { @@ -303,8 +355,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte setSourceName(Bundle.ContextViewer_downloadSource()); setSourceText(webDownloadArtifactToString(associatedArtifact)); } else if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == associatedArtifact.getArtifactTypeID()) { - setSourceName(Bundle.ContextViewer_recentDocs()); - setSourceText(recentDocArtifactToString(associatedArtifact)); + setUsageName(Bundle.ContextViewer_recentDocs()); + setUsageText(recentDocArtifactToString(associatedArtifact)); } } @@ -318,6 +370,15 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte jSourceNameLabel.setText(nameLabel); } + /** + * Sets the usage label string. + * + * @param nameLabel String value for usage label. + */ + private void setUsageName(String nameLabel) { + jUsageNameLabel.setText(nameLabel); + } + /** * Sets the source text string. * @@ -332,6 +393,24 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte jSourceTextLabel.setVisible(show); jSourceGoToResultButton.setEnabled(show); jSourceLabel.setVisible(show); + jUsageLabel.setVisible(show); + } + + /** + * Sets the Usage text string. + * + * @param text String value for Usage text. + */ + private void setUsageText(String text) { + jUsageTextLabel.setText(text); + showUsageText(!text.isEmpty()); + } + + private void showUsageText(boolean show) { + jUsageTextLabel.setVisible(show); + jUsageGoToResultButton.setEnabled(show); + jUsageLabel.setVisible(show); + jSourceLabel.setVisible(show); } /** @@ -371,16 +450,21 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte * @throws TskCoreException */ @NbBundle.Messages({ - "ContextViewer.file=File", - "ContextViewer.on=On" + "ContextViewer.on=Opened on", + "ContextViewer.unknown=Opened on unknown time" }) private String recentDocArtifactToString(BlackboardArtifact artifact) throws TskCoreException { StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN); Map attributesMap = getAttributesMap(artifact); + BlackboardAttribute attribute = attributesMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME); + if (BlackboardArtifact.ARTIFACT_TYPE.TSK_RECENT_OBJECT.getTypeID() == artifact.getArtifactTypeID()) { - appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH, attributesMap, Bundle.ContextViewer_file()); - appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, Bundle.ContextViewer_on()); + if (attribute.getValueLong() > 0) { + appendAttributeString(sb, BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME, attributesMap, Bundle.ContextViewer_on()); + } else { + sb.append(Bundle.ContextViewer_unknown()); + } } return sb.toString(); } @@ -472,5 +556,9 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte private javax.swing.JLabel jSourceLabel; private javax.swing.JLabel jSourceNameLabel; private javax.swing.JLabel jSourceTextLabel; + private javax.swing.JButton jUsageGoToResultButton; + private javax.swing.JLabel jUsageLabel; + private javax.swing.JLabel jUsageNameLabel; + private javax.swing.JLabel jUsageTextLabel; // End of variables declaration//GEN-END:variables } From 2b10038796be37c9b920dd8e049538afc7164f3b Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Thu, 5 Mar 2020 10:11:30 -0500 Subject: [PATCH 68/77] Update Bundle.properties Missed file in commit --- .../autopsy/contentviewers/contextviewer/Bundle.properties | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties index efe92bd0f6..6a74bbcb06 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties @@ -2,3 +2,7 @@ ContextViewer.jSourceGoToResultButton.text=Go to Result ContextViewer.jSourceTextLabel.text=jLabel2 ContextViewer.jSourceNameLabel.text=jSourceNameLabel ContextViewer.jSourceLabel.text=Source +ContextViewer.jUsageGoToResultButton.text=Go to Result +ContextViewer.jUsageLabel.text=Usage +ContextViewer.jUsageNameLabel.text=jSourceNameLabel +ContextViewer.jUsageTextLabel.text=jLabel2 From 34f49c9840af3cf0731dc931ecf1887c9b34b026 Mon Sep 17 00:00:00 2001 From: Mark McKinnon Date: Thu, 5 Mar 2020 11:29:42 -0500 Subject: [PATCH 69/77] Indent goto button and change on to at indented goto button more and change text from on to at --- .../contextviewer/Bundle.properties-MERGED | 4 +- .../contextviewer/ContextViewer.form | 54 ++++++++++--------- .../contextviewer/ContextViewer.java | 44 +++++++-------- 3 files changed, 53 insertions(+), 49 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED index aafa549431..76df8c7b3c 100755 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/Bundle.properties-MERGED @@ -15,8 +15,8 @@ ContextViewer.message=Message ContextViewer.messageFrom=From ContextViewer.messageOn=On ContextViewer.messageTo=To -ContextViewer.on=Opened on +ContextViewer.on=Opened at ContextViewer.recentDocs=Recent Documents: ContextViewer.title=Context ContextViewer.toolTip=Displays context for selected file. -ContextViewer.unknown=Opened on unknown time +ContextViewer.unknown=Opened at unknown time diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form index ab4771fc71..020705e938 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.form @@ -24,36 +24,38 @@ - + + + + - - + + + + + - - - - - - - - - - - - - + + + - - - - - - - - + + + + + + + + + + + + + + @@ -76,9 +78,9 @@ - + - + diff --git a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java index 0e8e03f5b1..0c457be704 100644 --- a/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java +++ b/Core/src/org/sleuthkit/autopsy/contentviewers/contextviewer/ContextViewer.java @@ -125,27 +125,29 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jSourceLabel) + .addComponent(jUsageLabel) .addGroup(layout.createSequentialGroup() + .addGap(6, 6, 6) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSourceLabel) - .addComponent(jUsageLabel) .addGroup(layout.createSequentialGroup() - .addGap(6, 6, 6) - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addGroup(layout.createSequentialGroup() - .addComponent(jSourceNameLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)) - .addGroup(layout.createSequentialGroup() - .addComponent(jUsageNameLabel) - .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) - .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE))))) - .addGap(36, 36, 36)) + .addComponent(jSourceNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jSourceTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addComponent(jUsageNameLabel) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jUsageTextLabel, javax.swing.GroupLayout.DEFAULT_SIZE, 192, Short.MAX_VALUE))))) + .addGap(36, 36, 36)) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() - .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) - .addComponent(jSourceGoToResultButton) - .addComponent(jUsageGoToResultButton)) - .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))) + .addGap(45, 45, 45) + .addComponent(jUsageGoToResultButton)) + .addGroup(layout.createSequentialGroup() + .addGap(46, 46, 46) + .addComponent(jSourceGoToResultButton))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) @@ -164,9 +166,9 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jUsageNameLabel) .addComponent(jUsageTextLabel)) - .addGap(18, 18, 18) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) .addComponent(jUsageGoToResultButton) - .addGap(0, 60, Short.MAX_VALUE)) + .addGap(0, 62, Short.MAX_VALUE)) ); }// //GEN-END:initComponents @@ -450,8 +452,8 @@ public final class ContextViewer extends javax.swing.JPanel implements DataConte * @throws TskCoreException */ @NbBundle.Messages({ - "ContextViewer.on=Opened on", - "ContextViewer.unknown=Opened on unknown time" + "ContextViewer.on=Opened at", + "ContextViewer.unknown=Opened at unknown time" }) private String recentDocArtifactToString(BlackboardArtifact artifact) throws TskCoreException { StringBuilder sb = new StringBuilder(ARTIFACT_STR_MAX_LEN); From 98941ab783b7043bc57328f94e1758fe2f056b80 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Thu, 5 Mar 2020 13:21:52 -0500 Subject: [PATCH 70/77] Use try-with-resources for resource management. --- .../datamodel/RdbmsCentralRepoFactory.java | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java index 09f103a038..66227ea366 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/RdbmsCentralRepoFactory.java @@ -774,10 +774,8 @@ public class RdbmsCentralRepoFactory { * @return True if success, false otherwise. */ private boolean insertDefaultAccountsTablesContent(Connection conn) { - Statement stmt = null; - try { - stmt = conn.createStatement(); - + + try (Statement stmt = conn.createStatement()) { // Populate the account_types table for (Account.Type type : Account.Type.PREDEFINED_ACCOUNT_TYPES) { int correlationTypeId = getCorrelationTypeIdForAccountType(conn, type); @@ -790,16 +788,8 @@ public class RdbmsCentralRepoFactory { } catch (SQLException ex) { LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in Accounts tables."), ex); return false; - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ex2) { - LOGGER.log(Level.SEVERE, "Error closing statement.", ex2); - } - } - } - + } + return true; } @@ -812,10 +802,7 @@ public class RdbmsCentralRepoFactory { */ private boolean insertDefaultPersonaTablesContent(Connection conn) { - Statement stmt = null; - try { - stmt = conn.createStatement(); - + try (Statement stmt = conn.createStatement()) { // populate the confidence table for (Confidence confidence : Persona.Confidence.values()) { String sqlString = "INSERT INTO confidence (confidence_id, description) VALUES ( " + confidence.getLevel() + ", '" + confidence.toString() + "')" //NON-NLS @@ -833,16 +820,8 @@ public class RdbmsCentralRepoFactory { } catch (SQLException ex) { LOGGER.log(Level.SEVERE, String.format("Failed to populate default data in Persona tables."), ex); return false; - } finally { - if (stmt != null) { - try { - stmt.close(); - } catch (SQLException ex2) { - LOGGER.log(Level.SEVERE, "Error closing statement.", ex2); - } - } - } - + } + return true; } From ad873dbd2d585ae52b6c019927e8776c1a65166f Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 5 Mar 2020 20:17:47 -0500 Subject: [PATCH 71/77] 6105 Clean up and bug fixes for GPX Parser --- .../GPX_Module/GPX_Parser_Module.py | 210 +++++++----------- 1 file changed, 82 insertions(+), 128 deletions(-) diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index d33084ccac..0769408f2a 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -37,8 +37,12 @@ from org.sleuthkit.datamodel import BlackboardArtifact from org.sleuthkit.datamodel import BlackboardAttribute from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper -from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypoint -from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints +from org.sleuthkit.datamodel.blackboardutils.attributes import TskGeoWaypointsUtil +from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil import GeoWaypointList +from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList import GeoWaypoint +from org.sleuthkit.datamodel.blackboardutils.attributes import TskGeoTrackpointsUtil +from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil import GeoTrackPointList +from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList import GeoTrackPoint from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestModule from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException @@ -63,20 +67,15 @@ import gpxpy.parser class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter): moduleName = "GPX Parser" - - # True - Verbose debugging messages sent to log file. - # False - Verbose debugging turned off. - debuglevel = False def getModuleDisplayName(self): return self.moduleName - # TODO: Give it a description def getModuleDescription(self): return "Module that extracts GEO data from GPX files." def getModuleVersionNumber(self): - return "1.1" + return "1.2" def isDataSourceIngestModuleFactory(self): return True @@ -88,10 +87,14 @@ class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter): # Data Source-level ingest module. One gets created per data source. class GPXParserDataSourceIngestModule(DataSourceIngestModule): - _logger = Logger.getLogger(GPXParserDataSourceIngestModuleFactory.moduleName) + # True - Verbose debugging messages sent to log file. + # False - Verbose debugging turned off. + writeDebugMsgs = True + + logger = Logger.getLogger(GPXParserDataSourceIngestModuleFactory.moduleName) def log(self, level, msg): - self._logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) + self.logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) def __init__(self): self.context = None @@ -105,179 +108,130 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule): # We don't know how much work there is yet. progressBar.switchToIndeterminate() - - # This will work in 4.0.1 and beyond. - # Use blackboard class to index blackboard artifacts for keyword search. - blackboard = Case.getCurrentCase().getServices().getBlackboard() - # Get the sleuthkitcase + # Get the case database and its blackboard. skCase = Case.getCurrentCase().getSleuthkitCase() + blackboard = skCase.getBlackboard() - # In the name and then count and read them. - fileManager = Case.getCurrentCase().getServices().getFileManager() - + # Get any files with a .gpx extension. + # It would perhaps be better to get these files by MIME type instead. + # RC: It would also be better if this were a file level ingest module so it could process files extracted from archives. + fileManager = Case.getCurrentCase().getServices().getFileManager() files = fileManager.findFiles(dataSource, "%.gpx") - # TODO: Would like to change this to find files based on mimetype rather than extension. - #files = findFiles(dataSource, "text/xml") - #if (file.isMimeType('text/xml') == False): + # Update the progress bar now that we know how much work there is to do. numFiles = len(files) - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "found " + str(numFiles) + " files") + if self.writeDebugMsgs: self.log(Level.INFO, "Found " + str(numFiles) + " GPX files") progressBar.switchToDeterminate(numFiles) - fileCount = 0; - # Get module name for adding attributes + # Get the module name, it will be needed for adding attributes moduleName = GPXParserDataSourceIngestModuleFactory.moduleName + + # Check if a folder for this is present in the case Temp directory. + # If not, create it. + dirName = os.path.join(Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module") + try: + os.stat(dirName) + except: + os.mkdir(dirName) + + # Create a temp file name. It appears that we cannot close and delete + # this file, but we can overwrite it for each file we need to process. + fileName = os.path.join(dirName, "tmp.gpx") + fileCount = 0; for file in files: - # Get the GeoArtifactsHelper - geoArtifactHelper = GeoArtifactsHelper(skCase, moduleName, file) + # Create a GeoArtifactsHelper for this file. + geoArtifactHelper = GeoArtifactsHelper(skCase, moduleName, None, file) # Check if the user pressed cancel while we were busy. if self.context.isJobCancelled(): return IngestModule.ProcessResult.OK - #self.log(Level.INFO, "GPX: Processing file: " + file.getName()) + if self.writeDebugMsgs: self.log(Level.INFO, "Processing " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")") fileCount += 1 - # Check if module folder is present. If not, create it. - dirName = os.path.join(Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module") - try: - os.stat(dirName) - except: - os.mkdir(dirName) - fileName = os.path.join(dirName, "tmp.gpx") - - # Check to see if temporary file exists. If it does, remove it. - if os.path.exists(fileName): - try: - os.remove(fileName) - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX:\t" + "FILE DELETED " + fileName ) - except: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX:\t" + "FILE NOT DELETED " + fileName) - - # This writes the file to the local file system. + # Write the file so that it can be parsed by gpxpy. localFile = File(fileName) ContentUtils.writeToFile(file, localFile) - # Send to gpxpy for parsing. + # Send the file to gpxpy for parsing. gpxfile = open(fileName) try: gpx = gpxpy.parse(gpxfile) - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX:\t" + "FILE PARSED") - except: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.SEVERE, "GPX:\t" + file.getName() + " - FILE NOT PARSED") + if self.writeDebugMsgs: self.log(Level.INFO, "Parsed " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")") + except Exception as e: + self.log(Level.WARNING, "Error parsing file " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e)) continue if gpx: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX: TRACKS") + if self.writeDebugMsgs: self.log(Level.INFO, "Processing tracks from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")") for track in gpx.tracks: for segment in track.segments: - geoPointList = ArrayList() + geoPointList = TskGeoTrackpointsUtil.GeoTrackPointList() for point in segment.points: - + elevation = 0 if point.elevation != None: elevation = point.elevation - dateTime = 0 + timeStamp = 0 try: if (point.time != None): - datetime = long(time.mktime(point.time.timetuple())) - except: - pass + timeStamp = long(time.mktime(point.time.timetuple())) + except Exception as e: + self.log(Level.WARNING, "Error getting track timestamp from " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e) - geoPointList.add(GeoWaypoint.GeoTrackPoint(point.latitude, point.longitude, elevation, 0, 0, 0, dateTime)) + geoPointList.addPoint(GeoTrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp)) try: - # Add the trackpoint using the helper class - geoartifact = geoArtifactHelper.addTrack("Trackpoint", geoPointList) + geoArtifactHelper.addTrack("Track", geoPointList, None) except Blackboard.BlackboardException as e: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.SEVERE, "GPX: Error using geo artifact helper with blackboard " ) + self.log(Level.SEVERE, "Error posting GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage()) except TskCoreException as e: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.SEVERE, "GPX: Error using geo artifact helper tskcoreexception" ) + self.log(Level.SEVERE, "Error creating GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage()) - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX: WAYPOINTS") + if self.writeDebugMsgs: self.log(Level.INFO, "Processing waypoints from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")") for waypoint in gpx.waypoints: - attributes = ArrayList() - art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK) - - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, waypoint.latitude)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, waypoint.longitude)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG.getTypeID(), moduleName, "Waypoint")) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, waypoint.name)) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "GPXParser")) - - art.addAttributes(attributes) try: - # Post the artifact to blackboard - skCase.getBlackboard().postArtifact(art, moduleName) + art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK) + + attributes = ArrayList() + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, waypoint.latitude)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, waypoint.longitude)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG.getTypeID(), moduleName, "Waypoint")) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, waypoint.name)) + attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "GPXParser")) + art.addAttributes(attributes) + + blackboard.postArtifact(art, moduleName) + except Blackboard.BlackboardException as e: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.SEVERE, "GPX: Error using geo artifact helper with blackboard for waypoints" ) + self.log(Level.SEVERE, "Error posting GPS bookmark artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage()) + except TskCoreException as e: + self.log(Level.SEVERE, "Error creating GPS bookmark artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage()) - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX: ROUTES") + if self.writeDebugMsgs: self.log(Level.INFO, "Processing routes from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")") for route in gpx.routes: - firstTimeThru = 0 - startingPoint = list() - endingPoint = list() + + geoWaypointList = TskGeoWaypointsUtil.GeoWaypointList() + for point in route.points: - # If first time in loop only populate starting point - if (firstTimeThru == 0): - startingPoint.append((point.latitude, point.longitude)) - firstTimeThru = 1 - else: - startingPoint.append((point.latitude, point.longitude)) - endingPoint.append((point.latitude, point.longitude)) + geoWaypointList.addPoint(point.latitude, point.longitude, elevation, point.name) - if (len(endingPoint) > 0): - # get length of ending point as this ensures that we have equal points to process. - for i in range(0,len(endingPoint) -1): - attributes = ArrayList() - art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE) - - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), moduleName, startingPoint[i][0])) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID(), moduleName, startingPoint[i][1])) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID(), moduleName, endingPoint[i][0])) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID(), moduleName, endingPoint[i][1])) - - art.addAttributes(attributes) - - try: - # Post the artifact to blackboard - skCase.getBlackboard().postArtifact(art, moduleName) - except Blackboard.BlackboardException as e: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.SEVERE, "GPX: Error using geo artifact helper with blackboard for waypoints" ) - else: - if (len(startingPoint) > 0): - attributes = ArrayList() - art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_ROUTE) - - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START.getTypeID(), moduleName, startingPoint[0][0])) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START.getTypeID(), moduleName, startingPoint[0][1])) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END.getTypeID(), moduleName, startingPoint[0][0])) - attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END.getTypeID(), moduleName, startingPoint[0][1])) - - art.addAttributes(attributes) - - try: - # Post the artifact to blackboard - skCase.getBlackboard().postArtifact(art, moduleName) - except Blackboard.BlackboardException as e: - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.SEVERE, "GPX: Error using geo artifact helper with blackboard for waypoints" ) - + try: + geoArtifactHelper.addRoute(None, None, geoWaypointList, None) + except Blackboard.BlackboardException as e: + self.log("Error posting GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage()) + except TskCoreException as e: + self.log(Level.SEVERE, "Error creating GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage()) # Update the progress bar. progressBar.progress(fileCount) - if os.path.exists(fileName): - try: - os.remove(fileName) - if GPXParserDataSourceIngestModuleFactory.debuglevel: self.log(Level.INFO, "GPX:\t" + "FILE DELETED") - except: - self.log(Level.SEVERE, "GPX:\t" + "FILE NOT DELETED") # Post a message to the ingest messages inbox. - message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, "GPX Parser Data Source Ingest Module", "Found %d files" % fileCount) + message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, moduleName, "Processed %d files" % fileCount) IngestServices.getInstance().postMessage(message) return IngestModule.ProcessResult.OK; From a5a532dc9eae2fb9fcd61595a8c01c72be405472 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 5 Mar 2020 20:20:24 -0500 Subject: [PATCH 72/77] 6105 Clean up and bug fixes for GPX Parser --- InternalPythonModules/GPX_Module/GPX_Parser_Module.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index 0769408f2a..7800b5f849 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -87,11 +87,8 @@ class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter): # Data Source-level ingest module. One gets created per data source. class GPXParserDataSourceIngestModule(DataSourceIngestModule): - # True - Verbose debugging messages sent to log file. - # False - Verbose debugging turned off. - writeDebugMsgs = True - logger = Logger.getLogger(GPXParserDataSourceIngestModuleFactory.moduleName) + writeDebugMsgs = True def log(self, level, msg): self.logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) From 174644f13fb2af036eddb325f1f5bb928c618837 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 5 Mar 2020 20:22:55 -0500 Subject: [PATCH 73/77] 6105 Clean up and bug fixes for GPX Parser --- InternalPythonModules/GPX_Module/GPX_Parser_Module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index 7800b5f849..6b61e28fc8 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -124,7 +124,7 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule): # Get the module name, it will be needed for adding attributes moduleName = GPXParserDataSourceIngestModuleFactory.moduleName - # Check if a folder for this is present in the case Temp directory. + # Check if a folder for this module is present in the case Temp directory. # If not, create it. dirName = os.path.join(Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module") try: From f2e8e01a0c7769893296e7365b4c9681519dffb2 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 5 Mar 2020 20:25:28 -0500 Subject: [PATCH 74/77] 6105 Clean up and bug fixes for GPX Parser --- InternalPythonModules/GPX_Module/GPX_Parser_Module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index 6b61e28fc8..933505e243 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -178,7 +178,7 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule): if (point.time != None): timeStamp = long(time.mktime(point.time.timetuple())) except Exception as e: - self.log(Level.WARNING, "Error getting track timestamp from " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e) + self.log(Level.WARNING, "Error getting track timestamp from " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e)) geoPointList.addPoint(GeoTrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp)) From 118d02b1a0e9394da939b4560ae9d1f5c4a4f499 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 6 Mar 2020 11:19:36 -0500 Subject: [PATCH 75/77] 6105 Clean up and bug fixes for GPX Parser --- InternalPythonModules/GPX_Module/GPX_Parser_Module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index 933505e243..44e9217f4d 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -88,7 +88,7 @@ class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter): class GPXParserDataSourceIngestModule(DataSourceIngestModule): logger = Logger.getLogger(GPXParserDataSourceIngestModuleFactory.moduleName) - writeDebugMsgs = True + writeDebugMsgs = False def log(self, level, msg): self.logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg) From 77a8bb89535e1ffd00163ea3509c864768907b89 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Fri, 6 Mar 2020 16:27:11 -0500 Subject: [PATCH 76/77] 6107 prompt user to use CR only in release mode --- .../eventlisteners/Installer.java | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index 208f201a30..b9e5cd2d40 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -32,6 +32,7 @@ import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoException; import org.sleuthkit.autopsy.core.RuntimeProperties; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.ModuleSettings; +import org.sleuthkit.autopsy.coreutils.Version; /** * Install event listeners during module initialization @@ -59,21 +60,38 @@ public class Installer extends ModuleInstall { @NbBundle.Messages({ "Installer.initialCreateSqlite.title=Enable Central Repository?", "Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to enable it?", - "Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. " + - "You can use this to ignore previously seen files and make connections between cases." + "Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. " + + "You can use this to ignore previously seen files and make connections between cases." }) @Override public void restored() { Case.addPropertyChangeListener(pcl); ieListener.installListeners(); + if (Version.getBuildType() == Version.Type.RELEASE) { + centralRepoCheckAndSetup(); + } + // now run regular module startup code + try { + CentralRepoDbManager.upgradeDatabase(); + } catch (CentralRepoException ex) { + LOGGER.log(Level.SEVERE, "There was an error while upgrading the central repository database", ex); + if (RuntimeProperties.runningWithGUI()) { + reportUpgradeError(ex); + } + } + } - + /** + * Check if CR has been previously configured or initialized and if not + * prompt user to set up. + */ + private void centralRepoCheckAndSetup() { Map centralRepoSettings = ModuleSettings.getConfigSettings("CentralRepository"); String initializedStr = centralRepoSettings.get("initialized"); - + // check to see if the repo has been initialized asking to setup cr boolean initialized = Boolean.parseBoolean(initializedStr); - + // if it hasn't received that flag, check for a previous install where cr is already setup if (!initialized) { boolean prevRepo = Boolean.parseBoolean(centralRepoSettings.get("db.useCentralRepo")); @@ -91,13 +109,13 @@ public class Installer extends ModuleInstall { try { SwingUtilities.invokeAndWait(() -> { try { - String dialogText = - "" + - "
" + - "

" + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.messageHeader") + "

" + - "

" + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.messageDesc") + "

" + - "
" + - ""; + String dialogText + = "" + + "
" + + "

" + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.messageHeader") + "

" + + "

" + NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.messageDesc") + "

" + + "
" + + ""; if (JOptionPane.YES_OPTION == JOptionPane.showConfirmDialog(WindowManager.getDefault().getMainWindow(), dialogText, @@ -120,23 +138,13 @@ public class Installer extends ModuleInstall { try { setupDefaultSqlite(); } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); + LOGGER.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); reportUpgradeError(ex); } } ModuleSettings.setConfigSetting("CentralRepository", "initialized", "true"); - } - - // now run regular module startup code - try { - CentralRepoDbManager.upgradeDatabase(); - } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "There was an error while upgrading the central repository database", ex); - if (RuntimeProperties.runningWithGUI()) { - reportUpgradeError(ex); - } } } @@ -145,15 +153,15 @@ public class Installer extends ModuleInstall { manager.setupDefaultSqliteDb(); } - @NbBundle.Messages({ "Installer.centralRepoUpgradeFailed.title=Central repository disabled" }) + @NbBundle.Messages({"Installer.centralRepoUpgradeFailed.title=Central repository disabled"}) private void reportUpgradeError(CentralRepoException ex) { try { SwingUtilities.invokeAndWait(() -> { JOptionPane.showMessageDialog(null, - ex.getUserMessage(), - NbBundle.getMessage(this.getClass(), - "Installer.centralRepoUpgradeFailed.title"), - JOptionPane.ERROR_MESSAGE); + ex.getUserMessage(), + NbBundle.getMessage(this.getClass(), + "Installer.centralRepoUpgradeFailed.title"), + JOptionPane.ERROR_MESSAGE); }); } catch (InterruptedException | InvocationTargetException e) { LOGGER.log(Level.WARNING, e.getMessage(), e); From ce49d54ca0fa87e84bb98d55c2ed88e43d3d0544 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Fri, 6 Mar 2020 20:10:39 -0500 Subject: [PATCH 77/77] Make sure package installer for CR does no popup --- .../eventlisteners/Bundle.properties-MERGED | 2 +- .../eventlisteners/Installer.java | 181 ++++++++++++------ 2 files changed, 127 insertions(+), 56 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED index cd654a5b37..e3c99ded13 100755 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Bundle.properties-MERGED @@ -8,5 +8,5 @@ IngestEventsListener.prevExists.text=Previously Seen Devices (Central Repository IngestEventsListener.prevTaggedSet.text=Previously Tagged As Notable (Central Repository) Installer.centralRepoUpgradeFailed.title=Central repository disabled Installer.initialCreateSqlite.messageDesc=It will store information about all hashes and identifiers that you process. You can use this to ignore previously seen files and make connections between cases. -Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to? +Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to enable it? Installer.initialCreateSqlite.title=Enable Central Repository? diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java index b9e5cd2d40..9f888e43f2 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/eventlisteners/Installer.java @@ -1,7 +1,7 @@ /* - * Central Repository + * Autopsy Forensic Browser * - * Copyright 2015-2017 Basis Technology Corp. + * Copyright 2017-2020 Basis Technology Corp. * Contact: carrier sleuthkit org * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -35,17 +35,37 @@ import org.sleuthkit.autopsy.coreutils.ModuleSettings; import org.sleuthkit.autopsy.coreutils.Version; /** - * Install event listeners during module initialization + * Adds/removes application event listeners responsible for adding data to the + * central repository, sets up a default, single-user SQLite central repository + * if no central repository is configured, and updates the central repository + * schema as required. + * + * TODO (Jira-6108): At first glance, this package seems to have become a rather + * strange package for the "package installer" for the CR to reside in. The + * org.sleuthkit.autopsy.centralrepository package would seem to be more + * appropriate with so much going on. However, having a central repository + * schema update occur in a "package installer" with no user feedback is not + * optimal. Furthermore, for a multi-user (collaborative) installation, a schema + * update should be done in a more controlled way by acquiring an exclusive + * coordination service lock and requiring shared locks to be acquired by nodes + * with open cases. */ public class Installer extends ModuleInstall { - private static final Logger LOGGER = Logger.getLogger(Installer.class.getName()); + private static final Logger logger = Logger.getLogger(Installer.class.getName()); private static final long serialVersionUID = 1L; - private final CaseEventListener pcl = new CaseEventListener(); - private final IngestEventsListener ieListener = new IngestEventsListener(); - private static Installer instance; + private final CaseEventListener caseEventListener = new CaseEventListener(); + private final IngestEventsListener ingestEventListener = new IngestEventsListener(); + /** + * Gets the singleton "package installer" used by the registered Installer + * for the Autopsy-Core module located in the org.sleuthkit.autopsy.core + * package. + * + * @return The "package installer" singleton for the + * org.sleuthkit.autopsy.centralrepository.eventlisteners package. + */ public synchronized static Installer getDefault() { if (instance == null) { instance = new Installer(); @@ -53,10 +73,25 @@ public class Installer extends ModuleInstall { return instance; } + /** + * Constructs the singleton "package installer" used by the registered + * Installer for the Autopsy-Core module located in the + * org.sleuthkit.autopsy.core package. + */ private Installer() { super(); } + /* + * Adds/removes application event listeners responsible for adding data to + * the central repository, sets up a default, single-user SQLite central + * repository if no central repository is configured, and updates the + * central repository schema as required. + * + * Called by the registered Installer for the Autopsy-Core module located in + * the org.sleuthkit.autopsy.core package when the already installed + * Autopsy-Core module is restored (during application startup). + */ @NbBundle.Messages({ "Installer.initialCreateSqlite.title=Enable Central Repository?", "Installer.initialCreateSqlite.messageHeader=The Central Repository is not enabled. Would you like to enable it?", @@ -65,27 +100,31 @@ public class Installer extends ModuleInstall { }) @Override public void restored() { - Case.addPropertyChangeListener(pcl); - ieListener.installListeners(); + addApplicationEventListeners(); + if (Version.getBuildType() == Version.Type.RELEASE) { - centralRepoCheckAndSetup(); - } - // now run regular module startup code - try { - CentralRepoDbManager.upgradeDatabase(); - } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "There was an error while upgrading the central repository database", ex); - if (RuntimeProperties.runningWithGUI()) { - reportUpgradeError(ex); - } + setupDefaultCentralRepository(); } + + updateCentralRepoSchema(); } /** - * Check if CR has been previously configured or initialized and if not - * prompt user to set up. + * Adds the application event listeners responsible for adding data to the + * central repository. */ - private void centralRepoCheckAndSetup() { + private void addApplicationEventListeners() { + Case.addPropertyChangeListener(caseEventListener); + ingestEventListener.installListeners(); + } + + /** + * Checks if the central repository has been set up and configured. If not, + * either offers to perform set up (running with a GUI) or does the set up + * unconditionally (not running with a GUI, e.g., in an automated ingest + * node). + */ + private void setupDefaultCentralRepository() { Map centralRepoSettings = ModuleSettings.getConfigSettings("CentralRepository"); String initializedStr = centralRepoSettings.get("initialized"); @@ -122,25 +161,25 @@ public class Installer extends ModuleInstall { NbBundle.getMessage(this.getClass(), "Installer.initialCreateSqlite.title"), JOptionPane.YES_NO_OPTION)) { - setupDefaultSqlite(); + setupDefaultSqliteCentralRepo(); } } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); + logger.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); - reportUpgradeError(ex); + doMessageBoxIfRunningInGUI(ex); } }); } catch (InterruptedException | InvocationTargetException ex) { - LOGGER.log(Level.SEVERE, "There was an error while running the swing utility invoke later while creating the central repository database", ex); + logger.log(Level.SEVERE, "There was an error while running the swing utility invoke later while creating the central repository database", ex); } } // if no GUI, just initialize else { try { - setupDefaultSqlite(); + setupDefaultSqliteCentralRepo(); } catch (CentralRepoException ex) { - LOGGER.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); + logger.log(Level.SEVERE, "There was an error while initializing the central repository database", ex); - reportUpgradeError(ex); + doMessageBoxIfRunningInGUI(ex); } } @@ -148,43 +187,75 @@ public class Installer extends ModuleInstall { } } - private void setupDefaultSqlite() throws CentralRepoException { + /** + * Sets up a default single-user SQLite central repository. + * + * @throws CentralRepoException If there is an error setting up teh central + * repository. + */ + private void setupDefaultSqliteCentralRepo() throws CentralRepoException { CentralRepoDbManager manager = new CentralRepoDbManager(); manager.setupDefaultSqliteDb(); } - @NbBundle.Messages({"Installer.centralRepoUpgradeFailed.title=Central repository disabled"}) - private void reportUpgradeError(CentralRepoException ex) { + /** + * Update the central repository schema. + */ + private void updateCentralRepoSchema() { try { - SwingUtilities.invokeAndWait(() -> { - JOptionPane.showMessageDialog(null, - ex.getUserMessage(), - NbBundle.getMessage(this.getClass(), - "Installer.centralRepoUpgradeFailed.title"), - JOptionPane.ERROR_MESSAGE); - }); - } catch (InterruptedException | InvocationTargetException e) { - LOGGER.log(Level.WARNING, e.getMessage(), e); + CentralRepoDbManager.upgradeDatabase(); + } catch (CentralRepoException ex) { + logger.log(Level.SEVERE, "An error occurred updating the central repository schema", ex); + if (RuntimeProperties.runningWithGUI()) { + doMessageBoxIfRunningInGUI(ex); + } } - } - @Override - public boolean closing() { - //platform about to close - - return true; + /** + * Display a central repository exception in a message box if running with a + * GUI. + * + * @param ex The exception. + */ + @NbBundle.Messages({"Installer.centralRepoUpgradeFailed.title=Central repository disabled"}) + private void doMessageBoxIfRunningInGUI(CentralRepoException ex) { + if (RuntimeProperties.runningWithGUI()) { + try { + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog(null, + ex.getUserMessage(), + NbBundle.getMessage(this.getClass(), "Installer.centralRepoUpgradeFailed.title"), + JOptionPane.ERROR_MESSAGE); + }); + } catch (InterruptedException | InvocationTargetException e) { + logger.log(Level.WARNING, e.getMessage(), e); + } + } } @Override public void uninstalled() { - //module is being unloaded - - Case.removePropertyChangeListener(pcl); - pcl.shutdown(); - ieListener.shutdown(); - ieListener.uninstallListeners(); - - // TODO: remove thread pool + /* + * TODO (Jira-6108): This code is erronoeous. As documented at + * http://bits.netbeans.org/dev/javadoc/org-openide-modules/org/openide/modules/ModuleInstall.html#uninstalled-- + * + * "Called when the module is disabled while the application is still + * running. Should remove whatever functionality that it had registered + * in ModuleInstall.restored(). + * + * Beware: in practice there is no way to + * ensure that this method will really be called. The module might + * simply be deleted or disabled while the application is not running. + * In fact this is always the case in NetBeans 6.0; the Plugin Manager + * only uninstalls or disables modules between restarts. This method + * will still be called if you reload a module during development." + * + * THIS CODE IS NEVER EXECUTED. + */ + Case.removePropertyChangeListener(caseEventListener); + caseEventListener.shutdown(); + ingestEventListener.shutdown(); + ingestEventListener.uninstallListeners(); } }