Merged in develop

This commit is contained in:
U-BASIS\dsmyda 2020-04-07 18:56:51 -04:00
commit f34ea63870
24 changed files with 283 additions and 200 deletions

View File

@ -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

View File

@ -532,8 +532,8 @@
<binary-origin>release/modules/ext/google-http-client-1.29.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/sleuthkit-postgresql-4.8.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.8.0.jar</binary-origin>
<runtime-relative-path>ext/sleuthkit-postgresql-4.9.0.jar</runtime-relative-path>
<binary-origin>release/modules/ext/sleuthkit-postgresql-4.9.0.jar</binary-origin>
</class-path-extension>
<class-path-extension>
<runtime-relative-path>ext/bcpkix-jdk15on-1.60.jar</runtime-relative-path>

View File

@ -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;

View File

@ -284,9 +284,13 @@ public class CorrelationAttributeUtil {
// Get the account type from the artifact
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 = CentralRepository.getInstance().getAccountTypeByName(accountTypeStr);

View File

@ -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<CorrelationAttributeInstance.Type> types = CentralRepository.getInstance().getDefinedCorrelationTypes();
Collections.sort(types, new Comparator<CorrelationAttributeInstance.Type>() {
//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
*/

View File

@ -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<CorrelationCase
private static final Logger logger = Logger.getLogger(CorrelationCaseChildNodeFactory.class.getName());
private Map<Integer, CorrelationAttributeInstance.Type> correlationTypeMap;
private final Set<Account> accounts;
/**
@ -108,22 +108,15 @@ final class CorrelationCaseChildNodeFactory extends ChildFactory<CorrelationCase
*
* @throws CentralRepoException
*/
private CorrelationAttributeInstance.Type getCorrelationType(Account.Type accountType) throws CentralRepoException {
if (correlationTypeMap == null) {
correlationTypeMap = new HashMap<>();
List<CorrelationAttributeInstance.Type> 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();
return CentralRepository.getInstance().getCorrelationTypeById(corrTypeId);
}
return null;
}
/**

View File

@ -247,6 +247,8 @@ public class MessageViewer extends JPanel implements RelationshipsViewer {
*/
private void showMessagesPane() {
switchCard("messages");
Outline outline = rootTablePane.getOutlineView().getOutline();
outline.clearSelection();
}
/**

View File

@ -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,113 @@ 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) {
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. No case is open.", ex);
}
}
if (StringUtils.isBlank(summaryText)) {
String firstLines = getFirstLines(file);
String translatedFirstLines = getTranslatedVersion(firstLines);
if (!StringUtils.isBlank(translatedFirstLines)) {
summaryText = translatedFirstLines;
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. No case is open.", ex);
}
}
} 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) {
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
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
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);
}
}
/**

View File

@ -2,7 +2,7 @@
*
* Autopsy Forensic Browser
*
* Copyright 2019 Basis Technology Corp.
* Copyright 2019-2020 Basis Technology Corp.
* contact: carrier <at> sleuthkit <dot> org
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -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<Waypoint.Property> 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 {

View File

@ -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<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) {
private GeoTrackPoints getPointsList(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> 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<Waypoint.Property> 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<Waypoint.Property> createPropertyList(GeoTrackPoint point) {
private List<Waypoint.Property> createPropertyList(GeoTrackPoints.TrackPoint point) {
List<Waypoint.Property> list = new ArrayList<>();
Long timestamp = point.getTimeStamp();

View File

@ -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<String, Integer> columnLookup, String[] values) throws DroneIngestException {
private TrackPoint createTrackPoint(Map<String, Integer> 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,

View File

@ -52,6 +52,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;
import org.sleuthkit.autopsy.centralrepository.datamodel.CentralRepository;
/**
@ -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"})

View File

@ -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());

View File

@ -57,6 +57,7 @@ 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.datamodel.AbstractFile;
/**
@ -83,6 +84,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 +189,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);

View File

@ -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.GeoWaypoints import Waypoint
from org.sleuthkit.datamodel.blackboardutils.attributes import GeoTrackPoints
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
@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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.attributes 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)

View File

@ -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.GeoTrackPoints import 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)

View File

@ -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

View File

@ -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

View File

@ -1,3 +1,3 @@
<project name="TSK_VERSION">
<property name="TSK_VERSION" value="4.8.0"/>
<property name="TSK_VERSION" value="4.9.0"/>
</project>

View File

@ -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<String> sets)
- org.sleuthkit.autopsy.report.TableReportModule.addSetElement(String elementName)
- org.sleuthkit.autopsy.report.TableReportModule.startTable(List<String> titles)
- org.sleuthkit.autopsy.report.TableReportModule.endTable()
- org.sleuthkit.autopsy.report.TableReportModule.addRow(List<String> 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<String> row) for every "row" of data it finds, or startTable(List<String> 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<FileReportDataTypes> headers)
- org.sleuthkit.autopsy.report.FileReportModule.endTable()
- org.sleuthkit.autopsy.report.FileReportModule.addRow(AbstractFile toAdd, List<FileReportDataTypes> 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<FileReportDataTypes> columns) for every abstract file in the case. Developers are guaranteed that the order of method calls will be startReport(), startTable(List<FileReportDataTypes> headers), addRow(AbstractFile toAdd, List<FileReportDataTypes> columns), AbstractFile toAdd, List<FileReportDataTypes> 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
<folder name="Services">
<file name="org-sleuthkit-autopsy-report-ReportHTML.instance">
<attr name="instanceOf" stringvalue="org.sleuthkit.autopsy.report.TableReportModule"/>
<attr name="instanceCreate" methodvalue="org.sleuthkit.autopsy.report.ReportHTML.getDefault"/>
<attr name="position" intvalue="910"/>
</file>
</folder>
@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

View File

@ -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...