mirror of
https://github.com/overcuriousity/autopsy-flatpak.git
synced 2025-07-12 16:06:15 +00:00
Merged in develop
This commit is contained in:
commit
f34ea63870
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,6 +247,8 @@ public class MessageViewer extends JPanel implements RelationshipsViewer {
|
||||
*/
|
||||
private void showMessagesPane() {
|
||||
switchCard("messages");
|
||||
Outline outline = rootTablePane.getOutlineView().getOutline();
|
||||
outline.clearSelection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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"})
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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...
|
||||
|
Loading…
x
Reference in New Issue
Block a user