From 995701d9c8cf9bd15573f6c9185a9dc54157039a Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Fri, 27 Mar 2020 09:22:34 -0400 Subject: [PATCH 01/21] Added a properychange listener to HashLookupSettingsPanel --- .../hashdatabase/HashLookupSettingsPanel.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java index ebe59fe535..c0f5a05104 100644 --- a/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java +++ b/Core/src/org/sleuthkit/autopsy/modules/hashdatabase/HashLookupSettingsPanel.java @@ -53,6 +53,7 @@ import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.CentralRepoHashS import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb.KnownFilesType; import org.sleuthkit.datamodel.TskCoreException; import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.HashDb; +import org.sleuthkit.autopsy.modules.hashdatabase.HashDbManager.SetEvt; /** * Instances of this class provide a comprehensive UI for managing the hash sets @@ -94,6 +95,17 @@ public final class HashLookupSettingsPanel extends IngestModuleGlobalSettingsPan } } }); + + HashDbManager.getInstance().addPropertyChangeListener(new PropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent evt) { + String propName = evt.getPropertyName(); + if(propName.equals(SetEvt.DB_ADDED.toString()) || + propName.equals(SetEvt.DB_DELETED.toString())) { + hashSetTableModel.refreshModel(); + } + } + }); } @NbBundle.Messages({"HashLookupSettingsPanel.Title=Global Hash Lookup Settings"}) From 09972174104631f649fbf7df56f9df4a18cef00d Mon Sep 17 00:00:00 2001 From: apriestman Date: Tue, 31 Mar 2020 14:53:33 -0400 Subject: [PATCH 02/21] Updated documentation on writing report modules --- docs/doxygen/modReport.dox | 69 +++++--------------------------------- 1 file changed, 8 insertions(+), 61 deletions(-) diff --git a/docs/doxygen/modReport.dox b/docs/doxygen/modReport.dox index 5799314acf..563a151c43 100644 --- a/docs/doxygen/modReport.dox +++ b/docs/doxygen/modReport.dox @@ -3,63 +3,18 @@ \section report_summary Overview Report modules allow Autopsy users to create different report types. Autopsy comes with modules to generate HTML and Excel artifact reports, a tab delimited File report, a Keyhole Markup Language (KML) report for Google Earth data, and a body file for timeline creation. You can make additional modules to create custom output formats. -There are three types of reporting modules that differ in how the data is organized. -- Table report modules organize the data into tables. If your output is in table format, this type of module will be easier to make because Autopsy does a lot of the organizing work for you. -- File report modules are also table-based, but they specifically deal with reporting on the Files in the case, not artifacts. -- General report modules are free form and you are allowed to organize the output however you want. - -Table report modules require their subclasses to override methods to start and end tables, and add rows to those tables. These methods are provided data, generated from a default configuration panel, for the module to report on. Because of this, when creating a table report module one only needs to focus on how to display the data, not how to find it. - -File report modules are similar to table report modules, but only require their sub-classes to start and end a single table, and add rows to that table. The methods are given an AbstractFile and a list of FileReportDataTypes, which specify what information about the file should be added to the report. The data can be extracted from the file by calling the FileReportDataTypes getValue method with the file as it's argument. - -On the other hand, general report modules have a single method to generate the report. This method gives the module freedom to find and process any data it so chooses. General modules also have the ability to provide a configuration panel, allowing the user to choose from various displayed settings. The report module may then use the user's selection to generate a more specific report. +All custom report modules will be general report modules. General report modules have a single method to generate the report. This method gives the module freedom to find and process any data it so chooses. General modules also have the ability to provide a configuration panel, allowing the user to choose from various displayed settings. The report module may then use the user's selection to generate a more specific report. General modules are also given the responsibility of updating their report's progress bar and processing label in the UI. A progress panel is given to every general report module. It contains basic API to start, stop, and add to the progress bar, as well as update the processing label. The module is also expected to check the progress bar's status occasionally to see if the user has manually canceled the report. \section report_create_module Creating a Report Module -To create a report module, start off by creating a new Java or Python (Jython) class and implementing (Java) or inheriting (Jython) the appropriate interface: -- org.sleuthkit.autopsy.report.TableReportModule -- org.sleuthkit.autopsy.report.FileReportModule -- org.sleuthkit.autopsy.report.GeneralReportModule - -All three of these interfaces extend the org.sleuthkit.autopsy.report.ReportModule interface that defines the following methods: +To create a report module, start off by creating a new Java or Python (Jython) class and implementing (Java) or inheriting (Jython) from org.sleuthkit.autopsy.report.GeneralReportModule. You'll need to override multiple methods including the following: - org.sleuthkit.autopsy.report.ReportModule.getName() - org.sleuthkit.autopsy.report.ReportModule.getDescription() - org.sleuthkit.autopsy.report.ReportModule.getRelativeFilePath() - -These methods will be called by Autopsy when it is presenting the reporting UI to a user. - -\subsection report_create_module_table Creating A Table Report Module -If you implement TableReportModule, you should override the methods: -- org.sleuthkit.autopsy.report.TableReportModule.startReport(String path) -- org.sleuthkit.autopsy.report.TableReportModule.endReport() -- org.sleuthkit.autopsy.report.TableReportModule.startDataType(String title) -- org.sleuthkit.autopsy.report.TableReportModule.endDataType() -- org.sleuthkit.autopsy.report.TableReportModule.startSet(String setName) -- org.sleuthkit.autopsy.report.TableReportModule.endSet() -- org.sleuthkit.autopsy.report.TableReportModule.addSetIndex(List sets) -- org.sleuthkit.autopsy.report.TableReportModule.addSetElement(String elementName) -- org.sleuthkit.autopsy.report.TableReportModule.startTable(List titles) -- org.sleuthkit.autopsy.report.TableReportModule.endTable() -- org.sleuthkit.autopsy.report.TableReportModule.addRow(List row) -- org.sleuthkit.autopsy.report.TableReportModule.dateToString(long date) - -When generating table module reports, Autopsy will iterate through a list of user selected data, and call methods such as addRow(List row) for every "row" of data it finds, or startTable(List titles) for every new category it finds. Developers are guaranteed that every start of a data type, set, or table will be followed by an appropriate end. The focus for a table report module should be to take the given information and display it in a user friendly format. See org.sleuthkit.autopsy.report.ReportExcel for an example. - -\subsection report_create_module_file Creating a File Report Module -If you implement FileReportModule, the overriden methods will be: -- org.sleuthkit.autopsy.report.FileReportModule.startReport(String path) -- org.sleuthkit.autopsy.report.FileReportModule.endReport() -- org.sleuthkit.autopsy.report.FileReportModule.startTable(List headers) -- org.sleuthkit.autopsy.report.FileReportModule.endTable() -- org.sleuthkit.autopsy.report.FileReportModule.addRow(AbstractFile toAdd, List columns) - -As when generating table module reports, Autopsy will iterate through a list of user selected data (which are represented by FileReportDataTypes), and call addRow(AbstractFile toAdd, List columns) for every abstract file in the case. Developers are guaranteed that the order of method calls will be startReport(), startTable(List headers), addRow(AbstractFile toAdd, List columns), AbstractFile toAdd, List columns),..., endTable(), endReport(). - -\subsection report_create_module_general Creating a General Report Module - -If you implement GeneralReportModule, the overridden methods will be: - org.sleuthkit.autopsy.report.GeneralReportModule.generateReport(String reportPath, ReportProgressPanel progressPanel) + +If your report module requires configuration, you'll need to override: - org.sleuthkit.autopsy.report.GeneralReportModule.getConfigurationPanel() For general report modules, Autopsy will simply call the generateReport(String reportPath, ReportProgressPanel progressPanel) method and leave it up to the module to aquire and report data in its desired format. The only requirements are that the module saves to the given report path and updates the org.sleuthkit.autopsy.report.ReportProgressPanel as the report progresses. @@ -90,22 +45,14 @@ if (null == searchService) { \subsection report_create_module_layer Installing your Report Module -Report modules developed using Java must be registered in a layer.xml file. This file allows Autopsy to find the report module. +Adding a service provider annotation allows Autopsy to find your report module. -An example entry in a layer.xml is shown below: \code - - - - - - - +@ServiceProvider(service = GeneralReportModule.class) +public class SampleReportModule implements GeneralReportModule { \endcode -In the above example, "org-sleuthkit-autopsy-report-ReportHTML" should be replaced with the package path to your report module. - -It is also important to remember to include a getDefault() method in your report module. As shown in the code above, the instance to each report module is accessed via it's getDefault() method. +It is also important to remember to include a getDefault() method in your report module. As shown in the code above, the instance to each report module is accessed via its getDefault() method. For example: \code From c721a89f5fd928a5da89a4b2dfcc114d628208c0 Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 2 Apr 2020 17:40:08 -0400 Subject: [PATCH 03/21] 6217 Refactor geo json attr utils --- .../autopsy/geolocation/datamodel/Route.java | 18 +-- .../autopsy/geolocation/datamodel/Track.java | 116 +++++++++--------- .../autopsy/modules/drones/DATExtractor.java | 16 +-- .../GPX_Module/GPX_Parser_Module.py | 18 ++- .../android/googlemaplocation.py | 10 +- InternalPythonModules/android/oruxmaps.py | 7 +- 6 files changed, 93 insertions(+), 92 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java index 67de1e55ba..cbe54fe9c1 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -25,9 +25,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.TskGeoWaypointsUtil; -import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList.GeoWaypoint; -import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil.InvalidJsonException; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints; /** * A Route represents a TSK_GPS_ROUTE artifact which has a start and end point @@ -42,8 +42,6 @@ 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. @@ -119,9 +117,13 @@ public class Route extends GeoPath { } if (attribute != null) { - GeoWaypointList waypoints = attributeUtil.fromAttribute(attribute); - - for(GeoWaypoint waypoint: waypoints) { + GeoWaypoints waypoints; + try { + waypoints = BlackboardJsonAttrUtil.fromAttribute(attribute, GeoWaypoints.class); + } catch (InvalidJsonException ex) { + throw new GeoLocationDataException(String.format("Unable to parse waypoints in TSK_GEO_WAYPOINTS attribute (artifact object ID =%d)", artifact.getId()), ex); + } + for (GeoWaypoints.Waypoint 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 213bd6b5f5..68da242b8a 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Track.java @@ -1,5 +1,4 @@ /* - * * Autopsy Forensic Browser * * Copyright 2020 Basis Technology Corp. @@ -26,26 +25,24 @@ 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.TskGeoTrackpointsUtil; -import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList; -import org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint; +import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil; +import org.sleuthkit.datamodel.blackboardutils.attributes.BlackboardJsonAttrUtil.InvalidJsonException; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; /** * A GPS track with which wraps the TSK_GPS_TRACK artifact. */ -public final class Track extends GeoPath{ +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. - * + * * @param artifact - * - * @throws GeoLocationDataException + * + * @throws GeoLocationDataException */ public Track(BlackboardArtifact artifact) throws GeoLocationDataException { this(artifact, Waypoint.getAttributesFromArtifactAsMap(artifact)); @@ -53,49 +50,49 @@ public final class Track extends GeoPath{ /** * Construct a Track for the given artifact and attributeMap. - * - * @param artifact TSK_GPD_TRACK artifact - * @param attributeMap Map of the artifact attributes - * - * @throws GeoLocationDataException + * + * @param artifact TSK_GPD_TRACK artifact + * @param attributeMap Map of the artifact attributes + * + * @throws GeoLocationDataException */ private Track(BlackboardArtifact artifact, Map attributeMap) throws GeoLocationDataException { super(artifact, getTrackName(attributeMap)); - GeoTrackPointList points = getPointsList(attributeMap); + GeoTrackPoints points = getPointsList(attributeMap); buildPath(points, artifact); startTimestamp = points.getStartTime(); endTimeStamp = points.getEndTime(); } - + /** * Returns the start time of this track. - * - * @return Earliest time, or null if none was available. - * (seconds from java epoch) + * + * @return Earliest time, or null if none was available. (seconds from java + * epoch) */ public Long getStartTime() { return startTimestamp; } - + /** * Returns the end time of this track. - * - * @return Earliest timestamp, or null if none was available. - * (seconds from java epoch) + * + * @return Earliest timestamp, or null if none was available. (seconds from + * java epoch) */ public Long getEndTime() { return endTimeStamp; } /** - * Return the name of the track from the attributeMap. - * Track name is stored in the attribute TSK_NAME - * + * Return the name of the track from the attributeMap. Track name is stored + * in the attribute TSK_NAME + * * @param attributeMap - - * @return Track name or empty string if none was available. + * + * @return Track name or empty string if none was available. */ private static String getTrackName(Map attributeMap) { BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME); @@ -105,38 +102,41 @@ public final class Track extends GeoPath{ /** * Create the list of TrackWaypoints from the GeoTrackPoint list. - * - * @param points List of GeoTrackPoints - * + * + * @param points GeoTrackPoints object. * @param artifact The artifact to which these points belong - * - * @throws GeoLocationDataException + * + * @throws GeoLocationDataException */ @Messages({ "# {0} - track name", "GEOTrack_point_label_header=Trackpoint for track: {0}" }) - private void buildPath(GeoTrackPointList points, BlackboardArtifact artifact) - throws GeoLocationDataException { - for(GeoTrackPoint point: points) { + private void buildPath(GeoTrackPoints points, BlackboardArtifact artifact) throws GeoLocationDataException { + for (GeoTrackPoints.TrackPoint point : points) { addToPath(new TrackWaypoint(artifact, Bundle.GEOTrack_point_label_header(getLabel()), point)); } } /** - * Returns the list of GeoTrackPoints from the attributeMap. Creates the + * Returns the list of GeoTrackPoints from the attributeMap. Creates the * GeoTrackPoint list from the TSK_GEO_TRACKPOINTS attribute. - * + * * @param attributeMap Map of artifact attributes. - * + * * @return GeoTrackPoint list empty list if the attribute was not found. + * + * @throws GeoLocationDataException */ - private GeoTrackPointList getPointsList(Map attributeMap) { + private GeoTrackPoints getPointsList(Map attributeMap) throws GeoLocationDataException { BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_TRACKPOINTS); if (attribute != null) { - return attributeUtil.fromAttribute(attribute); + try { + return BlackboardJsonAttrUtil.fromAttribute(attribute, GeoTrackPoints.class); + } catch (InvalidJsonException ex) { + throw new GeoLocationDataException("Unable to parse track points in TSK_GEO_TRACKPOINTS attribute", ex); + } } - return null; } @@ -149,16 +149,16 @@ public final class Track extends GeoPath{ /** * Construct a TrackWaypoint. - * - * @param artifact the artifact to which this waypoint belongs - * + * + * @param artifact the artifact to which this waypoint belongs + * * @param pointLabel the label for the waypoint - * - * @param point GeoTrackPoint - * - * @throws GeoLocationDataException + * + * @param point GeoTrackPoint + * + * @throws GeoLocationDataException */ - TrackWaypoint(BlackboardArtifact artifact, String pointLabel, GeoTrackPoint point) throws GeoLocationDataException { + TrackWaypoint(BlackboardArtifact artifact, String pointLabel, GeoTrackPoints.TrackPoint point) throws GeoLocationDataException { super(artifact, pointLabel, point.getTimeStamp(), point.getLatitude(), @@ -172,10 +172,10 @@ public final class Track extends GeoPath{ } /** - * Overloaded to return a property list that is generated from - * the GeoTrackPoint instead of an artifact. - * - * @return unmodifiable list of Waypoint.Property + * Overloaded to return a property list that is generated from the + * GeoTrackPoint instead of an artifact. + * + * @return unmodifiable list of Waypoint.Property */ @Override public List getOtherProperties() { @@ -184,16 +184,16 @@ public final class Track extends GeoPath{ /** * Create a propertyList specific to GeoTrackPoints. - * + * * @param point GeoTrackPoint to get values from. - * + * * @return A list of Waypoint.properies. */ @Messages({ "Track_distanceTraveled_displayName=Distance traveled", "Track_distanceFromHome_displayName=Distance from home point" }) - private List createPropertyList(GeoTrackPoint point) { + private List createPropertyList(GeoTrackPoints.TrackPoint point) { List list = new ArrayList<>(); Long timestamp = point.getTimeStamp(); diff --git a/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java b/Core/src/org/sleuthkit/autopsy/modules/drones/DATExtractor.java index 97cfbd40be..3966317d15 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.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.TskGeoTrackpointsUtil.GeoTrackPointList; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints; +import org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints.TrackPoint; /** * Extract drone position data from DJI Phantom drones. @@ -111,7 +111,7 @@ final class DATExtractor extends DroneExtractor { } // Process the csv file - GeoTrackPointList trackPoints = processCSVFile(context, DATFile, csvFilePath); + GeoTrackPoints trackPoints = processCSVFile(context, DATFile, csvFilePath); if (trackPoints != null && !trackPoints.isEmpty()) { (new GeoArtifactsHelper(getSleuthkitCase(), getName(), "DatCon", DATFile)).addTrack(DATFile.getName(), trackPoints, null); @@ -188,8 +188,8 @@ final class DATExtractor extends DroneExtractor { * * @throws DroneIngestException */ - private GeoTrackPointList processCSVFile(IngestJobContext context, AbstractFile DATFile, String csvFilePath) throws DroneIngestException { - GeoTrackPointList trackPoints = new GeoTrackPointList(); + private GeoTrackPoints processCSVFile(IngestJobContext context, AbstractFile DATFile, String csvFilePath) throws DroneIngestException { + GeoTrackPoints trackPoints = new GeoTrackPoints(); try (BufferedReader reader = new BufferedReader(new FileReader(new File(csvFilePath)))) { // First read in the header line and process String line = reader.readLine(); @@ -201,7 +201,7 @@ final class DATExtractor extends DroneExtractor { } String[] values = line.split(","); //NON-NLS - GeoTrackPoint point = createTrackPoint(headerMap, values); + TrackPoint point = createTrackPoint(headerMap, values); if (point != null) { trackPoints.addPoint(point); } @@ -246,7 +246,7 @@ final class DATExtractor extends DroneExtractor { * * @throws DroneIngestException */ - private GeoTrackPoint createTrackPoint(Map columnLookup, String[] values) throws DroneIngestException { + private TrackPoint createTrackPoint(Map columnLookup, String[] values) throws DroneIngestException { Double latitude = getDoubleValue(columnLookup.get(HEADER_LAT), values); Double longitude = getDoubleValue(columnLookup.get(HEADER_LONG), values); @@ -256,7 +256,7 @@ final class DATExtractor extends DroneExtractor { return null; } - return new GeoTrackPoint(latitude, + return new TrackPoint(latitude, longitude, getDoubleValue(columnLookup.get(HEADER_ALTITUDE), values), null, diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index 6aeb84d5be..1c654503cb 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -37,12 +37,10 @@ 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 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.datamodel.blackboardutils.attributes import GeoWaypoints +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypoints.Waypoint +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints.TrackPoint from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestModule from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException @@ -166,7 +164,7 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule): 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 = TskGeoTrackpointsUtil.GeoTrackPointList() + geoPointList = GeoTrackPoints() for point in segment.points: elevation = 0 @@ -180,7 +178,7 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule): except Exception as 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)) + geoPointList.addPoint(TrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp)) try: geoArtifactHelper.addTrack("Track", geoPointList, None) @@ -213,10 +211,10 @@ class GPXParserDataSourceIngestModule(DataSourceIngestModule): if self.writeDebugMsgs: self.log(Level.INFO, "Processing routes from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")") for route in gpx.routes: - geoWaypointList = TskGeoWaypointsUtil.GeoWaypointList() + geoWaypoints = GeoWaypoints() for point in route.points: - geoWaypointList.addPoint(GeoWaypoint(point.latitude, point.longitude, point.elevation, point.name)) + geoWaypointList.addPoint(Waypoint(point.latitude, point.longitude, point.elevation, point.name)) try: geoArtifactHelper.addRoute(None, None, geoWaypointList, None) diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index 8e393dcee2..d2499cbf03 100644 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -43,8 +43,8 @@ from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.Blackboard import BlackboardException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper -from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil import GeoWaypointList -from org.sleuthkit.datamodel.blackboardutils.attributes.TskGeoWaypointsUtil.GeoWaypointList import GeoWaypoint +from org.sleuthkit.datamodel.blackboardutils import GeoWaypoints +from org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints import Waypoint import traceback import general @@ -117,9 +117,9 @@ class GoogleMapLocationAnalyzer(general.AndroidComponentAnalyzer): source_lat = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lat")) source_lng = GoogleMapLocationAnalyzer.convertGeo(resultSet.getString("source_lng")) - waypointlist = GeoWaypointList() - waypointlist.addPoint(GeoWaypoint(source_lat, source_lng, None, None)) - waypointlist.addPoint(GeoWaypoint(dest_lat, dest_lng, None, dest_address)) + waypointlist = GeoWaypoints() + waypointlist.addPoint(Waypoint(source_lat, source_lng, None, None)) + waypointlist.addPoint(Waypoint(dest_lat, dest_lng, None, dest_address)) artifactHelper.addRoute(dest_title, time, waypointlist, None) diff --git a/InternalPythonModules/android/oruxmaps.py b/InternalPythonModules/android/oruxmaps.py index 7a939e1972..23920af069 100644 --- a/InternalPythonModules/android/oruxmaps.py +++ b/InternalPythonModules/android/oruxmaps.py @@ -45,7 +45,8 @@ from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.Blackboard import BlackboardException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper -from org.sleuthkit.datamodel.blackboardutils.attributes import TskGeoTrackpointsUtil +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints.TrackPoint import traceback import general @@ -139,14 +140,14 @@ class OruxMapsAnalyzer(general.AndroidComponentAnalyzer): trackpointsQueryString = "SELECT trkptlat, trkptlon, trkptalt, trkpttime FROM trackpoints WHERE trkptseg = " + segmentId trackpointsResultSet = oruxMapsTrackpointsDb.runQuery(trackpointsQueryString) if trackpointsResultSet is not None: - geoPointList = TskGeoTrackpointsUtil.GeoTrackPointList() + geoPointList = GeoTrackPoints() while trackpointsResultSet.next(): latitude = trackpointsResultSet.getDouble("trkptlat") longitude = trackpointsResultSet.getDouble("trkptlon") altitude = trackpointsResultSet.getDouble("trkptalt") time = trackpointsResultSet.getLong("trkpttime") / 1000 # milliseconds since unix epoch - geoPointList.addPoint(TskGeoTrackpointsUtil.GeoTrackPointList.GeoTrackPoint(latitude, longitude, altitude, segmentName, 0, 0, 0, time)) + geoPointList.addPoint(TrackPoint(latitude, longitude, altitude, segmentName, 0, 0, 0, time)) try: geoartifact = geoArtifactHelper.addTrack(segmentName, geoPointList, None) From 528c0283a1b607036d8b2a060d18a71697c3974d Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 2 Apr 2020 20:20:56 -0400 Subject: [PATCH 04/21] 6217 Refactor geo json attr utils --- InternalPythonModules/GPX_Module/GPX_Parser_Module.py | 4 ++-- InternalPythonModules/android/googlemaplocation.py | 2 +- InternalPythonModules/android/oruxmaps.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py index 1c654503cb..fe92d0d659 100644 --- a/InternalPythonModules/GPX_Module/GPX_Parser_Module.py +++ b/InternalPythonModules/GPX_Module/GPX_Parser_Module.py @@ -38,9 +38,9 @@ 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 GeoWaypoints -from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypoints.Waypoint +from org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints import Waypoint from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints -from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints.TrackPoint +from org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints import TrackPoint from org.sleuthkit.autopsy.datamodel import ContentUtils from org.sleuthkit.autopsy.ingest import IngestModule from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException diff --git a/InternalPythonModules/android/googlemaplocation.py b/InternalPythonModules/android/googlemaplocation.py index d2499cbf03..2c33146b21 100644 --- a/InternalPythonModules/android/googlemaplocation.py +++ b/InternalPythonModules/android/googlemaplocation.py @@ -43,7 +43,7 @@ from org.sleuthkit.datamodel import Content from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.Blackboard import BlackboardException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper -from org.sleuthkit.datamodel.blackboardutils import GeoWaypoints +from org.sleuthkit.datamodel.blackboardutils.attributes import GeoWaypoints from org.sleuthkit.datamodel.blackboardutils.attributes.GeoWaypoints import Waypoint import traceback diff --git a/InternalPythonModules/android/oruxmaps.py b/InternalPythonModules/android/oruxmaps.py index 23920af069..283eab38b2 100644 --- a/InternalPythonModules/android/oruxmaps.py +++ b/InternalPythonModules/android/oruxmaps.py @@ -46,7 +46,7 @@ from org.sleuthkit.datamodel import TskCoreException from org.sleuthkit.datamodel.Blackboard import BlackboardException from org.sleuthkit.datamodel.blackboardutils import GeoArtifactsHelper from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints -from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints.TrackPoint +from org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints import TrackPoint import traceback import general From 8c6fdf6bc21e16226407c72b95dfb2a0992201ac Mon Sep 17 00:00:00 2001 From: Richard Cordovano Date: Thu, 2 Apr 2020 22:49:24 -0400 Subject: [PATCH 05/21] 6217 Refactor geo json attr utils --- Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java | 2 +- 1 file changed, 1 insertion(+), 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 cbe54fe9c1..13a23b30e3 100755 --- a/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java +++ b/Core/src/org/sleuthkit/autopsy/geolocation/datamodel/Route.java @@ -2,7 +2,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"); From 70b65b15dabf96b2e49bca2f02ecab2664e6680d Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 3 Apr 2020 09:45:02 -0400 Subject: [PATCH 06/21] 6219: TskCoreException thrown from normalizePhoneNum Do not attempt to create account when we do not have a valid phone number or email address. --- InternalPythonModules/android/calllog.py | 3 --- InternalPythonModules/android/general.py | 14 +++++--------- InternalPythonModules/android/textnow.py | 2 +- InternalPythonModules/android/whatsapp.py | 2 +- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/InternalPythonModules/android/calllog.py b/InternalPythonModules/android/calllog.py index 5b3faf0697..13775e80f7 100644 --- a/InternalPythonModules/android/calllog.py +++ b/InternalPythonModules/android/calllog.py @@ -103,10 +103,7 @@ class CallLogAnalyzer(general.AndroidComponentAnalyzer): calleeId = None timeStamp = resultSet.getLong("date") / 1000 - number = resultSet.getString("number") - if not general.isValidPhoneNumer(number): - number = None duration = resultSet.getLong("duration") # duration of call is in seconds name = resultSet.getString("name") # name of person dialed or called. None if unregistered diff --git a/InternalPythonModules/android/general.py b/InternalPythonModules/android/general.py index daa789a57c..4048c05c0f 100644 --- a/InternalPythonModules/android/general.py +++ b/InternalPythonModules/android/general.py @@ -45,19 +45,15 @@ def appendAttachmentList(msgBody, attachmentsList): """ Checks if the given string might be a phone number. """ -def isValidPhoneNumer(data): - try: - return CommunicationsUtils.normalizePhoneNum(data) is not None - except TskCoreException as ex: - return False +def isValidPhoneNumber(data): + return CommunicationsUtils.isValidPhoneNumber(data) + """ Checks if the given string is a valid email address. """ def isValidEmailAddress(data): - try: - return CommunicationsUtils.normalizeEmailAddress(data) is not None - except TskCoreException as ex: - return False + return CommunicationsUtils.isValidEmailAddress(data) + diff --git a/InternalPythonModules/android/textnow.py b/InternalPythonModules/android/textnow.py index e05763cae9..005e1191dd 100644 --- a/InternalPythonModules/android/textnow.py +++ b/InternalPythonModules/android/textnow.py @@ -286,7 +286,7 @@ class TextNowContactsParser(TskContactsParser): def get_phone(self): number = self.result_set.getString("number") - return (number if general.isValidPhoneNumer(number) else None) + return (number if general.isValidPhoneNumber(number) else None) def get_email(self): # occasionally the 'number' column may have an email address instead diff --git a/InternalPythonModules/android/whatsapp.py b/InternalPythonModules/android/whatsapp.py index 5346545450..c67502d22b 100644 --- a/InternalPythonModules/android/whatsapp.py +++ b/InternalPythonModules/android/whatsapp.py @@ -435,7 +435,7 @@ class WhatsAppContactsParser(TskContactsParser): def get_phone(self): number = self.result_set.getString("number") - return (number if general.isValidPhoneNumer(number) else None) + return (number if general.isValidPhoneNumber(number) else None) def get_email(self): # occasionally the 'number' column may have an email address instead From 88c04241a479b8847e578d405f2d0192a2136374 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 3 Apr 2020 12:49:41 -0400 Subject: [PATCH 07/21] 6236: Other occurrences not working for new types in CVT Summary panel --- .../CorrelationCaseChildNodeFactory.java | 27 ++++++++----------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java index 67e0366a9b..bfc859c524 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java @@ -28,6 +28,7 @@ import org.openide.nodes.ChildFactory; import org.openide.nodes.Children; import org.openide.nodes.Node; import org.openide.nodes.Sheet; +import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepoAccount; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeInstance; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationAttributeNormalizationException; import org.sleuthkit.autopsy.centralrepository.datamodel.CorrelationCase; @@ -45,7 +46,6 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory correlationTypeMap; private final Set accounts; /** @@ -108,22 +108,17 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory(); - List correcationTypeList = CentralRepository.getInstance().getDefinedCorrelationTypes(); - correcationTypeList.forEach((type) -> { - correlationTypeMap.put(type.getId(), type); - }); - } - - if (Account.Type.EMAIL.equals(accountType)) { - return correlationTypeMap.get(CorrelationAttributeInstance.EMAIL_TYPE_ID); - } else if (Account.Type.PHONE.equals(accountType)) { - return correlationTypeMap.get(CorrelationAttributeInstance.PHONE_TYPE_ID); - } else { - return null; + private CorrelationAttributeInstance.Type getCorrelationType(Account.Type accountType) throws CentralRepoException { + String accountTypeStr = accountType.getTypeName(); + if (Account.Type.DEVICE.getTypeName().equalsIgnoreCase(accountTypeStr) == false) { + CentralRepoAccount.CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr); + int corrTypeId = crAccountType.getCorrelationTypeId(); + CorrelationAttributeInstance.Type corrType = CentralRepository.getInstance().getCorrelationTypeById(corrTypeId); + + return corrType; } + + return null; } /** From 7b01f6e6c7486407f154517cfc739e93295070dd Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Fri, 3 Apr 2020 13:12:05 -0400 Subject: [PATCH 08/21] Addressed Codacy comment. --- .../relationships/CorrelationCaseChildNodeFactory.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java index bfc859c524..588e474303 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/CorrelationCaseChildNodeFactory.java @@ -113,9 +113,7 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory Date: Fri, 3 Apr 2020 15:04:08 -0400 Subject: [PATCH 09/21] 6229: SEVERE errors from CR failing to handle custom account types --- .../datamodel/CorrelationAttributeUtil.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index 14724fafb7..ea295c35d4 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -215,7 +215,14 @@ public class CorrelationAttributeUtil { if (Account.Type.DEVICE.getTypeName().equalsIgnoreCase(accountTypeStr) == false) { // Get the corresponding CentralRepoAccountType from the database. - CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr); + CentralRepoAccountType crAccountType; + try { + // @@TODO Vik-6136: CR currently does not know of custom account types. + // This try/catch prevents unnecessary exceptions, till CR handles implement custom account types + crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr); + } catch (CentralRepoException ex) { + return; + } int corrTypeId = crAccountType.getCorrelationTypeId(); CorrelationAttributeInstance.Type corrType = CentralRepository.getInstance().getCorrelationTypeById(corrTypeId); From b8aacf001919b1415dea1492e9d0c2c4233b34ab Mon Sep 17 00:00:00 2001 From: Brian Carrier Date: Fri, 3 Apr 2020 22:28:29 -0400 Subject: [PATCH 10/21] updated TSK version --- Core/nbproject/project.properties | 2 +- Core/nbproject/project.xml | 4 ++-- TSKVersion.xml | 2 +- unix_setup.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Core/nbproject/project.properties b/Core/nbproject/project.properties index 80e8cfd4d4..c7ceb01a4a 100644 --- a/Core/nbproject/project.properties +++ b/Core/nbproject/project.properties @@ -78,7 +78,7 @@ file.reference.javax.ws.rs-api-2.0.1.jar=release/modules/ext/javax.ws.rs-api-2.0 file.reference.cxf-core-3.0.16.jar=release/modules/ext/cxf-core-3.0.16.jar file.reference.cxf-rt-frontend-jaxrs-3.0.16.jar=release/modules/ext/cxf-rt-frontend-jaxrs-3.0.16.jar file.reference.cxf-rt-transports-http-3.0.16.jar=release/modules/ext/cxf-rt-transports-http-3.0.16.jar -file.reference.sleuthkit-postgresql-4.8.0.jar=release/modules/ext/sleuthkit-postgresql-4.8.0.jar +file.reference.sleuthkit-postgresql-4.9.0.jar=release/modules/ext/sleuthkit-postgresql-4.9.0.jar file.reference.curator-client-2.8.0.jar=release/modules/ext/curator-client-2.8.0.jar file.reference.curator-framework-2.8.0.jar=release/modules/ext/curator-framework-2.8.0.jar file.reference.curator-recipes-2.8.0.jar=release/modules/ext/curator-recipes-2.8.0.jar diff --git a/Core/nbproject/project.xml b/Core/nbproject/project.xml index 02d37221a7..4aa97960f3 100644 --- a/Core/nbproject/project.xml +++ b/Core/nbproject/project.xml @@ -532,8 +532,8 @@ release/modules/ext/google-http-client-1.29.0.jar - ext/sleuthkit-postgresql-4.8.0.jar - release/modules/ext/sleuthkit-postgresql-4.8.0.jar + ext/sleuthkit-postgresql-4.9.0.jar + release/modules/ext/sleuthkit-postgresql-4.9.0.jar ext/bcpkix-jdk15on-1.60.jar diff --git a/TSKVersion.xml b/TSKVersion.xml index 561c00581d..38e614169a 100644 --- a/TSKVersion.xml +++ b/TSKVersion.xml @@ -1,3 +1,3 @@ - + diff --git a/unix_setup.sh b/unix_setup.sh index badf2a1505..dc92f38236 100644 --- a/unix_setup.sh +++ b/unix_setup.sh @@ -5,7 +5,7 @@ # NOTE: update_sleuthkit_version.pl updates this value and relies # on it keeping the same name and whitespace. Don't change it. -TSK_VERSION=4.8.0 +TSK_VERSION=4.9.0 # In the beginning... From abedee28d95d3c6334d1243bed94a07c1ac5cf0d Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 6 Apr 2020 06:33:30 -0400 Subject: [PATCH 11/21] 6190 cleaned up translated basic summary code --- .../autopsy/filequery/FileSearch.java | 107 +++++++++++++++++- 1 file changed, 105 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index 5832625b73..0a9b14a8c0 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -23,6 +23,10 @@ import com.google.common.cache.CacheBuilder; import com.google.common.io.Files; import java.awt.Image; import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; import java.io.Reader; import java.nio.file.Paths; @@ -79,6 +83,9 @@ import org.sleuthkit.autopsy.textextractors.TextExtractor; import org.sleuthkit.autopsy.textextractors.TextExtractorFactory; import org.sleuthkit.autopsy.textsummarizer.TextSummarizer; import org.sleuthkit.autopsy.textsummarizer.TextSummary; +import org.sleuthkit.autopsy.texttranslation.NoServiceProviderException; +import org.sleuthkit.autopsy.texttranslation.TextTranslationService; +import org.sleuthkit.autopsy.texttranslation.TranslationException; /** * Main class to perform the file search. @@ -304,9 +311,105 @@ class FileSearch { } catch (TskCoreException ex) { logger.log(Level.WARNING, "Error getting children for file: " + file.getId(), ex); } - image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM, + image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM, Image.SCALE_SMOOTH); - return new TextSummary(getFirstLines(file), image, countOfImages); + String summaryText = null; + if (file.getMD5Hash() != null) { + summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); + } + if (StringUtils.isBlank(summaryText)) { + String firstLines = getFirstLines(file); + String translatedFirstLines = getTranslatedVersion(firstLines); + if (!StringUtils.isBlank(translatedFirstLines)) { + summaryText = translatedFirstLines; + if (file.getMD5Hash() != null) { + saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); + } + } else { + summaryText = firstLines; + } + } + return new TextSummary(summaryText, image, countOfImages); + } + + /** + * Provide an English version of the specified String if it is not English, + * translation is enabled, and it can be translated. + * + * @param documentString The String to provide an English version of. + * + * @return The English version of the provided String, or null if no + * translation occurred. + */ + private static String getTranslatedVersion(String documentString) { + if (!LANGUAGE_DETECTOR.detect(documentString).isLanguage("en")) { + try { + TextTranslationService translatorInstance = TextTranslationService.getInstance(); + if (translatorInstance.hasProvider()) { + String translatedResult = translatorInstance.translate(documentString); + if (translatedResult.isEmpty() == false) { + return translatedResult; + } + } + } catch (NoServiceProviderException | TranslationException ex) { + logger.log(Level.INFO, "Error translating string for summary", ex); + } + } + return null; + } + + /** + * Find and load a saved summary from the case folder for the specified + * file. + * + * @param summarySavePath The full path for the saved summary file. + * + * @return The summary found given the specified path, null if no summary + * was found. + */ + private static String getSavedSummary(String summarySavePath) { + if (summarySavePath == null) { + return null; + } + File savedFile = new File(summarySavePath); + if (savedFile.exists()) { + try (BufferedReader bReader = new BufferedReader(new FileReader(savedFile))) { + // pass the path to the file as a parameter + StringBuilder sBuilder = new StringBuilder(); + String sCurrentLine = bReader.readLine(); + while (sCurrentLine != null) { + sBuilder.append(sCurrentLine).append("\n"); + sCurrentLine = bReader.readLine(); + } + return sBuilder.toString(); + } catch (IOException ingored) { + //summary file may not exist or may be incomplete in which case return null so a summary can be generated + } + } else { + try { //if the file didn't exist make sure the parent directories exist before we move on to creating a summary + Files.createParentDirs(savedFile); + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to create summaries directory in case folder for file at: " + summarySavePath, ex); + } + } + return null; //no saved summary was able to be found + } + + /** + * Save a summary at the specified location. + * + * @param summary The text of the summary being saved. + * @param summarySavePath The full path for the saved summary file. + */ + private static void saveSummary(String summary, String summarySavePath) { + if (summarySavePath == null) { + return; //can't save a summary if we don't have a path + } + try (FileWriter myWriter = new FileWriter(summarySavePath)) { + myWriter.write(summary); + } catch (IOException ex) { + logger.log(Level.WARNING, "Unable to save summary at: " + summarySavePath, ex); + } } /** From fb63359844c5393c32d2f55e0a2f4ffbfed29bd8 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 6 Apr 2020 06:39:29 -0400 Subject: [PATCH 12/21] 6190 fix error handling --- .../autopsy/filequery/FileSearch.java | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index 0a9b14a8c0..32dceb9e8e 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -314,16 +314,24 @@ class FileSearch { image = image == null ? image : image.getScaledInstance(ImageUtils.ICON_SIZE_MEDIUM, ImageUtils.ICON_SIZE_MEDIUM, Image.SCALE_SMOOTH); String summaryText = null; - if (file.getMD5Hash() != null) { - summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); + if (file.getMd5Hash() != null) { + try { + summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); + } catch (NoCurrentCaseException ex) { + logger.log(Level.WARNING, "Unable to retrieve saved summary case not open", ex); + } } if (StringUtils.isBlank(summaryText)) { String firstLines = getFirstLines(file); String translatedFirstLines = getTranslatedVersion(firstLines); if (!StringUtils.isBlank(translatedFirstLines)) { summaryText = translatedFirstLines; - if (file.getMD5Hash() != null) { - saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); + if (file.getMd5Hash() != null) { + try { + saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); + } catch (NoCurrentCaseException ex) { + logger.log(Level.WARNING, "Unable to save translated summary case not open", ex); + } } } else { summaryText = firstLines; @@ -342,18 +350,16 @@ class FileSearch { * translation occurred. */ private static String getTranslatedVersion(String documentString) { - if (!LANGUAGE_DETECTOR.detect(documentString).isLanguage("en")) { - try { - TextTranslationService translatorInstance = TextTranslationService.getInstance(); - if (translatorInstance.hasProvider()) { - String translatedResult = translatorInstance.translate(documentString); - if (translatedResult.isEmpty() == false) { - return translatedResult; - } + try { + TextTranslationService translatorInstance = TextTranslationService.getInstance(); + if (translatorInstance.hasProvider()) { + String translatedResult = translatorInstance.translate(documentString); + if (translatedResult.isEmpty() == false) { + return translatedResult; } - } catch (NoServiceProviderException | TranslationException ex) { - logger.log(Level.INFO, "Error translating string for summary", ex); } + } catch (NoServiceProviderException | TranslationException ex) { + logger.log(Level.INFO, "Error translating string for summary", ex); } return null; } From edbe64af90fff8a6cfa372be88941cb5efa4e71e Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 6 Apr 2020 07:14:21 -0400 Subject: [PATCH 13/21] 6235 sort types combo box to ensure Files is first --- .../commonpropertiessearch/InterCasePanel.java | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java index f36f8ab520..5eb521f3d5 100644 --- a/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java +++ b/Core/src/org/sleuthkit/autopsy/commonpropertiessearch/InterCasePanel.java @@ -21,6 +21,7 @@ package org.sleuthkit.autopsy.commonpropertiessearch; import org.sleuthkit.autopsy.guiutils.DataSourceComboBoxModel; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -119,6 +120,13 @@ public final class InterCasePanel extends javax.swing.JPanel { this.correlationTypeFilters = new HashMap<>(); try { List types = CentralRepository.getInstance().getDefinedCorrelationTypes(); + Collections.sort(types, new Comparator() { + //The types should be sorted so that the File type is the first item in the combo box. + @Override + public int compare(CorrelationAttributeInstance.Type type1, CorrelationAttributeInstance.Type type2) { + return Integer.compare(type1.getId(), type2.getId()); + } + }); for (CorrelationAttributeInstance.Type type : types) { correlationTypeFilters.put(type.getDisplayName(), type); this.correlationTypeComboBox.addItem(type.getDisplayName()); @@ -295,7 +303,7 @@ public final class InterCasePanel extends javax.swing.JPanel { private void correlationTypeComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_correlationTypeComboBoxActionPerformed - boolean enableFileTypesFilter = this.correlationTypeComboBox.getSelectedItem().equals("Files"); + boolean enableFileTypesFilter = this.correlationTypeComboBox.getSelectedItem().equals("Files"); categoriesLabel.setEnabled(enableFileTypesFilter); allFileCategoriesRadioButton.setEnabled(enableFileTypesFilter); selectedFileCategoriesButton.setEnabled(enableFileTypesFilter); @@ -329,8 +337,8 @@ public final class InterCasePanel extends javax.swing.JPanel { // End of variables declaration//GEN-END:variables /** - * Get the map of cases which was used to populate the combo box on - * this panel. + * Get the map of cases which was used to populate the combo box on this + * panel. * * @return an unmodifiable copy of the map of cases */ @@ -339,8 +347,8 @@ public final class InterCasePanel extends javax.swing.JPanel { } /** - * Set the datamodel for the combo box which displays the cases in - * the central repository + * Set the datamodel for the combo box which displays the cases in the + * central repository * * @param dataSourceComboBoxModel the DataSourceComboBoxModel to use */ From 54d3cc53c3fabb341507f26ed61e7cdc1670d9a3 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 6 Apr 2020 07:20:15 -0400 Subject: [PATCH 14/21] 6190 fix codacy complaint --- Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index 32dceb9e8e..456a7210aa 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -384,7 +384,7 @@ class FileSearch { StringBuilder sBuilder = new StringBuilder(); String sCurrentLine = bReader.readLine(); while (sCurrentLine != null) { - sBuilder.append(sCurrentLine).append("\n"); + sBuilder.append(sCurrentLine).append('\n'); sCurrentLine = bReader.readLine(); } return sBuilder.toString(); From dd8f578ae35ad1e852ab3d8223c802692f725159 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 6 Apr 2020 07:48:00 -0400 Subject: [PATCH 15/21] 6190 improve error message --- Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index 456a7210aa..74a87c7a17 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -318,7 +318,7 @@ class FileSearch { try { summaryText = getSavedSummary(Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); } catch (NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to retrieve saved summary case not open", ex); + logger.log(Level.WARNING, "Unable to retrieve saved summary. No case is open.", ex); } } if (StringUtils.isBlank(summaryText)) { @@ -330,7 +330,7 @@ class FileSearch { try { saveSummary(summaryText, Paths.get(Case.getCurrentCaseThrows().getCacheDirectory(), "summaries", file.getMd5Hash() + "-default-" + PREVIEW_SIZE + "-translated.txt").toString()); } catch (NoCurrentCaseException ex) { - logger.log(Level.WARNING, "Unable to save translated summary case not open", ex); + logger.log(Level.WARNING, "Unable to save translated summary. No case is open.", ex); } } } else { From 27cd407d8676a90df77d9b85d5addc7459bc7159 Mon Sep 17 00:00:00 2001 From: Raman Arora Date: Mon, 6 Apr 2020 09:26:28 -0400 Subject: [PATCH 16/21] Search incoming account in the Account.PREDEFINED_ACCOUNT_TYPES list. --- .../datamodel/CorrelationAttributeUtil.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java index ea295c35d4..e5b0d7ab50 100644 --- a/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java +++ b/Core/src/org/sleuthkit/autopsy/centralrepository/datamodel/CorrelationAttributeUtil.java @@ -211,18 +211,15 @@ public class CorrelationAttributeUtil { BlackboardAttribute accountTypeAttribute = acctArtifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE)); String accountTypeStr = accountTypeAttribute.getValueString(); + // @@TODO Vik-6136: CR currently does not know of custom account types. + // Ensure there is a predefined account type for this account. + Account.Type predefinedAccountType = Account.Type.PREDEFINED_ACCOUNT_TYPES.stream().filter(type -> type.getTypeName().equalsIgnoreCase(accountTypeStr)).findAny().orElse(null); + // do not create any correlation attribute instance for a Device account - if (Account.Type.DEVICE.getTypeName().equalsIgnoreCase(accountTypeStr) == false) { + if (Account.Type.DEVICE.getTypeName().equalsIgnoreCase(accountTypeStr) == false && predefinedAccountType != null) { // Get the corresponding CentralRepoAccountType from the database. - CentralRepoAccountType crAccountType; - try { - // @@TODO Vik-6136: CR currently does not know of custom account types. - // This try/catch prevents unnecessary exceptions, till CR handles implement custom account types - crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr); - } catch (CentralRepoException ex) { - return; - } + CentralRepoAccountType crAccountType = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr); int corrTypeId = crAccountType.getCorrelationTypeId(); CorrelationAttributeInstance.Type corrType = CentralRepository.getInstance().getCorrelationTypeById(corrTypeId); From 76ef4fbd8e51248ccb9e7667c1a7f618b5026138 Mon Sep 17 00:00:00 2001 From: William Schaefer Date: Mon, 6 Apr 2020 09:31:43 -0400 Subject: [PATCH 17/21] 6190 make codacy happy --- Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java index 74a87c7a17..b25f83d195 100644 --- a/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java +++ b/Core/src/org/sleuthkit/autopsy/filequery/FileSearch.java @@ -390,6 +390,7 @@ class FileSearch { return sBuilder.toString(); } catch (IOException ingored) { //summary file may not exist or may be incomplete in which case return null so a summary can be generated + return null; //no saved summary was able to be found } } else { try { //if the file didn't exist make sure the parent directories exist before we move on to creating a summary @@ -397,8 +398,9 @@ class FileSearch { } catch (IOException ex) { logger.log(Level.WARNING, "Unable to create summaries directory in case folder for file at: " + summarySavePath, ex); } + return null; //no saved summary was able to be found } - return null; //no saved summary was able to be found + } /** From 618d2520a52d8a2432c81ccfd5989b1f8d80382b Mon Sep 17 00:00:00 2001 From: Kelly Kelly Date: Tue, 7 Apr 2020 11:09:29 -0400 Subject: [PATCH 18/21] Fixed CVT unthreaded selection issue --- .../autopsy/communications/relationships/MessageViewer.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java index 5e90d83c98..38e245aec3 100755 --- a/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java +++ b/Core/src/org/sleuthkit/autopsy/communications/relationships/MessageViewer.java @@ -247,6 +247,8 @@ public class MessageViewer extends JPanel implements RelationshipsViewer { */ private void showMessagesPane() { switchCard("messages"); + Outline outline = rootTablePane.getOutlineView().getOutline(); + outline.clearSelection(); } /** From 290a0fccea9f41a4d0900f24321ecc1ffec56f52 Mon Sep 17 00:00:00 2001 From: Ethan Roseman Date: Tue, 7 Apr 2020 14:26:03 -0400 Subject: [PATCH 19/21] 6249: Swapped toolbar button positions --- Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java | 2 +- .../autopsy/report/infrastructure/ReportWizardAction.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java index 3d610890da..a64809a07d 100644 --- a/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java +++ b/Core/src/org/sleuthkit/autopsy/casemodule/CaseCloseAction.java @@ -50,7 +50,7 @@ import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; @ActionID(category = "Tools", id = "org.sleuthkit.autopsy.casemodule.CaseCloseAction") @ActionRegistration(displayName = "#CTL_CaseCloseAct", lazy = false) @ActionReferences(value = { - @ActionReference(path = "Toolbars/Case", position = 106)}) + @ActionReference(path = "Toolbars/Case", position = 107)}) public final class CaseCloseAction extends CallableSystemAction implements Presenter.Toolbar { private static final long serialVersionUID = 1L; diff --git a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java index 5b3d661665..236263200a 100644 --- a/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java +++ b/Core/src/org/sleuthkit/autopsy/report/infrastructure/ReportWizardAction.java @@ -59,7 +59,7 @@ import org.sleuthkit.autopsy.report.ReportModule; @ActionReferences(value = { @ActionReference(path = "Menu/Tools", position = 301, separatorAfter = 399) , - @ActionReference(path = "Toolbars/Case", position = 107)}) + @ActionReference(path = "Toolbars/Case", position = 106)}) public final class ReportWizardAction extends CallableSystemAction implements Presenter.Toolbar, ActionListener { private static final Logger logger = Logger.getLogger(ReportWizardAction.class.getName()); From 87e3ba759c8a16e0b5c567c77a6013a7d481d4d8 Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 7 Apr 2020 14:36:40 -0400 Subject: [PATCH 20/21] Setting MIME type before indexing test file --- .../configuration/MultiUserTestTool.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java index 8504bfd7c0..8148c23faa 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java @@ -57,6 +57,8 @@ import org.sleuthkit.autopsy.ingest.IngestJobStartResult; import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.sleuthkit.autopsy.textextractors.TextExtractor; import org.sleuthkit.datamodel.AbstractFile; /** @@ -83,6 +85,7 @@ class MultiUserTestTool { "MultiUserTestTool.unableCreatFile=Unable to create a file in case output directory", "MultiUserTestTool.unableAddFileAsDataSource=Unable to add test file as data source to case", "MultiUserTestTool.unableToReadTestFileFromDatabase=Unable to read test file info from case database", + "MultiUserTestTool.unableToInitializeFilTypeDetector=Unable to initialize File Type Detector", "MultiUserTestTool.unableToUpdateKWSIndex=Unable to write to Keyword Search index", "MultiUserTestTool.unableToRunIngest=Unable to run ingest on test data source", "MultiUserTestTool.unexpectedError=Unexpected error while performing Multi User test", @@ -187,6 +190,16 @@ class MultiUserTestTool { } AbstractFile file = listOfFiles.get(0); + + // Set MIME type of the test file (required to test indexing) + FileTypeDetector fileTypeDetector = null; + try { + fileTypeDetector = new FileTypeDetector(); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + return Bundle.MultiUserTestTool_unableToInitializeFilTypeDetector() + ". " + ex.getMessage(); + } + String mimeType = fileTypeDetector.getMIMEType(file); + file.setMIMEType(mimeType); // write to KWS index KeywordSearchService kwsService = Lookup.getDefault().lookup(KeywordSearchService.class); From e853e3aab9a699dfe3ffd1935ce9936f39caadfa Mon Sep 17 00:00:00 2001 From: Eugene Livis Date: Tue, 7 Apr 2020 14:48:45 -0400 Subject: [PATCH 21/21] Setting MIME type before indexing test file --- .../autopsy/experimental/configuration/MultiUserTestTool.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java index 8148c23faa..c622d452b5 100755 --- a/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java +++ b/Experimental/src/org/sleuthkit/autopsy/experimental/configuration/MultiUserTestTool.java @@ -58,7 +58,6 @@ import org.sleuthkit.autopsy.ingest.IngestManager; import org.sleuthkit.autopsy.ingest.IngestModuleError; import org.sleuthkit.autopsy.keywordsearchservice.KeywordSearchService; import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; -import org.sleuthkit.autopsy.textextractors.TextExtractor; import org.sleuthkit.datamodel.AbstractFile; /**