merged in geolocation-refactor-branch

This commit is contained in:
Kelly Kelly 2019-11-05 15:16:31 -05:00
commit 3f16ff384e
17 changed files with 388 additions and 184 deletions

View File

@ -1,8 +1,11 @@
language: java
sudo: required
jobs:
include:
- os: linux
dist: bionic
os:
- linux
- os: osx
env:
global:
@ -12,6 +15,7 @@ addons:
apt:
update: true
packages:
- testdisk
- libafflib-dev
- libewf-dev
- libpq-dev
@ -29,11 +33,13 @@ addons:
update: true
packages:
- ant
- ant-optional
- wget
- libpq
- libewf
- gettext
- cppunit
- afflib
- testdisk
python:
- "2.7"
@ -43,9 +49,7 @@ before_install:
- python setupSleuthkitBranch.py
install:
- sudo apt-get install testdisk
- cd sleuthkit/sleuthkit
- ./travis_install_libs.sh
- pushd sleuthkit/sleuthkit && ./travis_install_libs.sh && popd
before_script:
- if [ $TRAVIS_OS_NAME = linux ]; then
@ -54,13 +58,13 @@ before_script:
export PATH=/usr/bin:$PATH;
unset JAVA_HOME;
fi
- if [ $TRAVIS_OS_NAME = osx ]; then
brew uninstall java --force;
brew cask uninstall java --force;
brew tap homebrew/cask-versions;
brew cask install corretto8;
export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-8.jdk/Contents/Home;
fi
- java -version
script:
- set -e
- echo "Building TSK..."
- ./bootstrap && ./configure --prefix=/usr && make
- pushd bindings/java/ && ant -q dist-PostgreSQL && popd
- echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r'
- cd $TRAVIS_BUILD_DIR/
- ant build
- echo -en 'travis_fold:end:script.build\\r'
script: ./travis_build.sh

View File

@ -56,6 +56,10 @@ import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
import org.sleuthkit.datamodel.TskException;
import org.netbeans.swing.etable.ETable;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
/**
* Instances of this class display the BlackboardArtifacts associated with the
@ -552,6 +556,16 @@ public class DataContentViewerArtifact extends javax.swing.JPanel implements Dat
value = dateFormatter.format(new java.util.Date(epoch * 1000));
}
break;
case JSON:
// @TODO: 5726 - return a multilevel bulleted list instead of prettyprint JSON
String jsonVal = attr.getValueString();
JsonParser parser = new JsonParser();
JsonObject json = parser.parse(jsonVal).getAsJsonObject();
Gson gson = new GsonBuilder().setPrettyPrinting().create();
value = gson.toJson(json);
break;
}
/*
* Attribute sources column.

View File

@ -122,6 +122,7 @@ public class ArtifactStringContent implements StringContent {
case LONG:
case DOUBLE:
case BYTE:
case JSON:
default:
value = attr.getDisplayString();
break;

View File

@ -38,12 +38,10 @@ import org.sleuthkit.autopsy.directorytree.ExternalViewerShortcutAction;
import org.sleuthkit.autopsy.geolocation.datamodel.GeoLocationDataException;
import org.sleuthkit.autopsy.geolocation.datamodel.Route;
import org.sleuthkit.datamodel.SleuthkitCase;
import org.sleuthkit.autopsy.geolocation.datamodel.ArtifactWaypoint;
import org.sleuthkit.autopsy.geolocation.datamodel.Waypoint;
import org.sleuthkit.autopsy.timeline.actions.ViewArtifactInTimelineAction;
import org.sleuthkit.autopsy.timeline.actions.ViewFileInTimelineAction;
import org.sleuthkit.datamodel.AbstractFile;
import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
import org.sleuthkit.datamodel.Content;
import org.sleuthkit.datamodel.TskCoreException;
@ -56,7 +54,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
private static final Logger logger = Logger.getLogger(MapWaypoint.class.getName());
private final ArtifactWaypoint dataModelWaypoint;
private final Waypoint dataModelWaypoint;
private final GeoPosition position;
/**
@ -64,7 +62,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
*
* @param dataModelWaypoint The datamodel waypoint to wrap
*/
private MapWaypoint(ArtifactWaypoint dataModelWaypoint) {
private MapWaypoint(Waypoint dataModelWaypoint) {
super(dataModelWaypoint.getLatitude(), dataModelWaypoint.getLongitude());
this.dataModelWaypoint = dataModelWaypoint;
position = new GeoPosition(dataModelWaypoint.getLatitude(), dataModelWaypoint.getLongitude());
@ -86,7 +84,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
* @throws GeoLocationDataException
*/
static List<MapWaypoint> getWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<ArtifactWaypoint> points = ArtifactWaypoint.getAllWaypoints(skCase);
List<Waypoint> points = Waypoint.getAllWaypoints(skCase);
List<Route> routes = Route.getRoutes(skCase);
for (Route route : routes) {
@ -95,7 +93,7 @@ final class MapWaypoint extends KdTree.XYZPoint implements org.jxmapviewer.viewe
List<MapWaypoint> mapPoints = new ArrayList<>();
for (ArtifactWaypoint point : points) {
for (Waypoint point : points) {
mapPoints.add(new MapWaypoint(point));
}

View File

@ -27,7 +27,7 @@ import org.sleuthkit.datamodel.TskCoreException;
/**
* Waypoint wrapper class for TSK_METADATA_EXIF artifacts.
*/
final class EXIFWaypoint extends ArtifactWaypoint {
final class EXIFWaypoint extends Waypoint {
/**
* Construct a way point with the given artifact.

View File

@ -26,7 +26,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* A Last Known Location Waypoint object.
*/
final class LastKnownWaypoint extends ArtifactWaypoint {
final class LastKnownWaypoint extends Waypoint {
/**
* Constructs a new waypoint.

View File

@ -36,12 +36,12 @@ import org.sleuthkit.datamodel.TskCoreException;
*
*/
public final class Route {
private final List<ArtifactWaypoint> points;
private final List<Waypoint> points;
private final Long timestamp;
// This list is not expected to change after construction so the
// constructor will take care of creating an unmodifiable List
private final List<ArtifactWaypoint.Property> immutablePropertiesList;
private final List<Waypoint.Property> immutablePropertiesList;
/**
* Gets the list of Routes from the TSK_GPS_ROUTE artifacts.
@ -77,14 +77,14 @@ public final class Route {
Route(BlackboardArtifact artifact) throws GeoLocationDataException {
points = new ArrayList<>();
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap = ArtifactWaypoint.getAttributesFromArtifactAsMap(artifact);
Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap = Waypoint.getAttributesFromArtifactAsMap(artifact);
points.add(getRouteStartPoint(artifact, attributeMap));
points.add(getRouteEndPoint(artifact, attributeMap));
BlackboardAttribute attribute = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
timestamp = attribute != null ? attribute.getValueLong() : null;
immutablePropertiesList = Collections.unmodifiableList(ArtifactWaypoint.createGeolocationProperties(attributeMap));
immutablePropertiesList = Collections.unmodifiableList(Waypoint.createGeolocationProperties(attributeMap));
}
/**
@ -92,7 +92,7 @@ public final class Route {
*
* @return List an unmodifiableList of ArtifactWaypoints for this route
*/
public List<ArtifactWaypoint> getRoute() {
public List<Waypoint> getRoute() {
return Collections.unmodifiableList(points);
}
@ -102,7 +102,7 @@ public final class Route {
*
* @return Map of key, value pairs.
*/
public List<ArtifactWaypoint.Property> getOtherProperties() {
public List<Waypoint.Property> getOtherProperties() {
return immutablePropertiesList;
}
@ -136,14 +136,15 @@ public final class Route {
@Messages({
"Route_Start_Label=Start"
})
private ArtifactWaypoint getRouteStartPoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
private Waypoint getRouteStartPoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
BlackboardAttribute latitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_START);
BlackboardAttribute longitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_START);
BlackboardAttribute altitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
BlackboardAttribute pointTimestamp = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
if (latitude != null && longitude != null) {
return new ArtifactWaypoint(artifact,
return new Waypoint(artifact,
Bundle.Route_Start_Label(),
pointTimestamp != null ? pointTimestamp.getValueLong() : null,
latitude.getValueDouble(),
@ -169,14 +170,15 @@ public final class Route {
@Messages({
"Route_End_Label=End"
})
private ArtifactWaypoint getRouteEndPoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
Waypoint getRouteEndPoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
BlackboardAttribute latitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END);
BlackboardAttribute longitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END);
BlackboardAttribute altitude = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE);
BlackboardAttribute pointTimestamp = attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME);
if (latitude != null && longitude != null) {
return new ArtifactWaypoint(artifact,
return new Waypoint(artifact,
Bundle.Route_End_Label(),
pointTimestamp != null ? pointTimestamp.getValueLong() : null,
latitude.getValueDouble(),

View File

@ -24,9 +24,9 @@ import org.sleuthkit.datamodel.BlackboardArtifact;
import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* A SearchWaypoint is a subclass of ArtifactWaypoint.
* A SearchWaypoint is a subclass of Waypoint.
*/
final class SearchWaypoint extends ArtifactWaypoint {
final class SearchWaypoint extends Waypoint {
/**
* Construct a waypoint for TSK_GPS_SEARCH artifact.

View File

@ -26,7 +26,7 @@ import org.sleuthkit.datamodel.BlackboardAttribute;
/**
* A wrapper class for TSK_GPS_TRACKPOINT artifacts.
*/
final class TrackpointWaypoint extends ArtifactWaypoint {
final class TrackpointWaypoint extends Waypoint {
/**
* Construct a waypoint for trackpoints.
*

View File

@ -37,7 +37,7 @@ import org.sleuthkit.datamodel.TskCoreException;
* Representation of a Waypoint created from a BlackboardArtifact.
*
*/
public class ArtifactWaypoint {
public class Waypoint {
final private Long timestamp;
final private Double longitude;
@ -50,13 +50,13 @@ public class ArtifactWaypoint {
// This list is not expected to change after construction. The
// constructor will take care of making an unmodifiable List
final private List<ArtifactWaypoint.Property> immutablePropertiesList;
final private List<Waypoint.Property> immutablePropertiesList;
/**
* This is a list of attributes that are already being handled by the
* by getter functions.
*/
static BlackboardAttribute.ATTRIBUTE_TYPE[] ALREADY_HANDLED_ATTRIBUTES = {
static private BlackboardAttribute.ATTRIBUTE_TYPE[] ALREADY_HANDLED_ATTRIBUTES = {
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE,
@ -68,7 +68,7 @@ public class ArtifactWaypoint {
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE_END,
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE_END,};
private static final Logger logger = Logger.getLogger(ArtifactWaypoint.class.getName());
private static final Logger logger = Logger.getLogger(Waypoint.class.getName());
/**
* Construct a waypoint with the given artifact.
@ -78,7 +78,7 @@ public class ArtifactWaypoint {
* @throws GeoLocationDataException Exception will be thrown if artifact did
* not have a valid longitude and latitude.
*/
ArtifactWaypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
Waypoint(BlackboardArtifact artifact) throws GeoLocationDataException {
this(artifact,
getAttributesFromArtifactAsMap(artifact));
}
@ -98,7 +98,7 @@ public class ArtifactWaypoint {
* @throws GeoLocationDataException Exception will be thrown if artifact did
* not have a valid longitude and latitude.
*/
ArtifactWaypoint(BlackboardArtifact artifact, String label, Long timestamp, Double latitude, Double longitude, Double altitude, AbstractFile image, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap, Route route) throws GeoLocationDataException {
Waypoint(BlackboardArtifact artifact, String label, Long timestamp, Double latitude, Double longitude, Double altitude, AbstractFile image, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap, Route route) throws GeoLocationDataException {
if (longitude == null || latitude == null) {
throw new GeoLocationDataException("Invalid waypoint, null value passed for longitude or latitude");
}
@ -124,7 +124,7 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
private ArtifactWaypoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
private Waypoint(BlackboardArtifact artifact, Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
this(artifact,
getLabelFromArtifact(attributeMap),
attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME) != null ? attributeMap.get(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_DATETIME).getValueLong() : null,
@ -207,7 +207,7 @@ public class ArtifactWaypoint {
*
* @return A List of waypoint properties
*/
public List<ArtifactWaypoint.Property> getOtherProperties() {
public List<Waypoint.Property> getOtherProperties() {
return immutablePropertiesList;
}
@ -276,8 +276,8 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
public static List<ArtifactWaypoint> getAllWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<ArtifactWaypoint> points = new ArrayList<>();
public static List<Waypoint> getAllWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<Waypoint> points = new ArrayList<>();
points.addAll(getTrackpointWaypoints(skCase));
points.addAll(getEXIFWaypoints(skCase));
@ -297,7 +297,7 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
public static List<ArtifactWaypoint> getTrackpointWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
public static List<Waypoint> getTrackpointWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<BlackboardArtifact> artifacts = null;
try {
artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_TRACKPOINT);
@ -305,10 +305,10 @@ public class ArtifactWaypoint {
throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_TRACKPOINT", ex);
}
List<ArtifactWaypoint> points = new ArrayList<>();
List<Waypoint> points = new ArrayList<>();
for (BlackboardArtifact artifact : artifacts) {
try {
ArtifactWaypoint point = new TrackpointWaypoint(artifact);
Waypoint point = new TrackpointWaypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_TRACKPOINT artifactID: %d", artifact.getArtifactID()));
@ -326,7 +326,7 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
static public List<ArtifactWaypoint> getEXIFWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
static public List<Waypoint> getEXIFWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<BlackboardArtifact> artifacts = null;
try {
artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF);
@ -334,11 +334,11 @@ public class ArtifactWaypoint {
throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);
}
List<ArtifactWaypoint> points = new ArrayList<>();
List<Waypoint> points = new ArrayList<>();
if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) {
try {
ArtifactWaypoint point = new EXIFWaypoint(artifact);
Waypoint point = new EXIFWaypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
// I am a little relucant to log this error because I suspect
@ -359,7 +359,7 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
public static List<ArtifactWaypoint> getSearchWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
public static List<Waypoint> getSearchWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<BlackboardArtifact> artifacts = null;
try {
artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_SEARCH);
@ -367,11 +367,11 @@ public class ArtifactWaypoint {
throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_SEARCH", ex);
}
List<ArtifactWaypoint> points = new ArrayList<>();
List<Waypoint> points = new ArrayList<>();
if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) {
try {
ArtifactWaypoint point = new SearchWaypoint(artifact);
Waypoint point = new SearchWaypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_SEARCH artifactID: %d", artifact.getArtifactID()));
@ -390,7 +390,7 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
public static List<ArtifactWaypoint> getLastKnownWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
public static List<Waypoint> getLastKnownWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<BlackboardArtifact> artifacts = null;
try {
artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_LAST_KNOWN_LOCATION);
@ -398,11 +398,11 @@ public class ArtifactWaypoint {
throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_LAST_KNOWN_LOCATION", ex);
}
List<ArtifactWaypoint> points = new ArrayList<>();
List<Waypoint> points = new ArrayList<>();
if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) {
try {
ArtifactWaypoint point = new LastKnownWaypoint(artifact);
Waypoint point = new LastKnownWaypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_LAST_KNOWN_LOCATION artifactID: %d", artifact.getArtifactID()));
@ -421,7 +421,7 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
public static List<ArtifactWaypoint> getBookmarkWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
public static List<Waypoint> getBookmarkWaypoints(SleuthkitCase skCase) throws GeoLocationDataException {
List<BlackboardArtifact> artifacts = null;
try {
artifacts = skCase.getBlackboardArtifacts(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK);
@ -429,11 +429,11 @@ public class ArtifactWaypoint {
throw new GeoLocationDataException("Unable to get artifacts for type: TSK_GPS_BOOKMARK", ex);
}
List<ArtifactWaypoint> points = new ArrayList<>();
List<Waypoint> points = new ArrayList<>();
if (artifacts != null) {
for (BlackboardArtifact artifact : artifacts) {
try {
ArtifactWaypoint point = new ArtifactWaypoint(artifact);
Waypoint point = new Waypoint(artifact);
points.add(point);
} catch (GeoLocationDataException ex) {
logger.log(Level.WARNING, String.format("No longitude or latitude available for TSK_GPS_BOOKMARK artifactID: %d", artifact.getArtifactID()));
@ -454,8 +454,8 @@ public class ArtifactWaypoint {
*
* @throws GeoLocationDataException
*/
static public List<ArtifactWaypoint.Property> createGeolocationProperties(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
List<ArtifactWaypoint.Property> list = new ArrayList<>();
static public List<Waypoint.Property> createGeolocationProperties(Map<BlackboardAttribute.ATTRIBUTE_TYPE, BlackboardAttribute> attributeMap) throws GeoLocationDataException {
List<Waypoint.Property> list = new ArrayList<>();
Set<BlackboardAttribute.ATTRIBUTE_TYPE> keys = new HashSet<>(attributeMap.keySet());
@ -467,7 +467,7 @@ public class ArtifactWaypoint {
String key = type.getDisplayName();
String value = attributeMap.get(type).getDisplayString();
list.add(new ArtifactWaypoint.Property(key, value));
list.add(new Waypoint.Property(key, value));
}
return list;
}

View File

@ -730,10 +730,15 @@ class KMLReport implements GeneralReportModule {
*
* @param route
*
* @return
* @return A HTML formatted list of the Route attributes
*/
<<<<<<< HEAD
private String getFormattedDetails(Route route) {
List<ArtifactWaypoint> points = route.getRoute();
=======
private String getFormattedDetails(Route route) {
List<Waypoint> points = route.getRoute();
>>>>>>> geolocation-datamodel-refactoring
StringBuilder result = new StringBuilder(); //NON-NLS
result.append(String.format("<h3>%s</h3>", Bundle.Route_Details_Header()))
@ -765,8 +770,13 @@ class KMLReport implements GeneralReportModule {
}
}
<<<<<<< HEAD
List<ArtifactWaypoint.Property> list = route.getOtherProperties();
for(ArtifactWaypoint.Property prop: list) {
=======
List<Waypoint.Property> list = route.getOtherProperties();
for(Waypoint.Property prop: list) {
>>>>>>> geolocation-datamodel-refactoring
String value = prop.getValue();
if(value != null && !value.isEmpty()) {
result.append(formatAttribute(prop.getDisplayName(), value));

View File

@ -768,6 +768,7 @@ public class PortableCaseReportModule implements ReportModule {
oldAttr.getValueLong()));
break;
case STRING:
case JSON:
newAttrs.add(new BlackboardAttribute(newAttributeType, String.join(",", oldAttr.getSources()),
oldAttr.getValueString()));
break;

View File

@ -50,6 +50,8 @@ final class CustomArtifactType {
private static final String BYTES_ATTR_DISPLAY_NAME = "Custom Bytes";
private static final String STRING_ATTR_TYPE_NAME = "CUSTOM_STRING_ATTRIBUTE";
private static final String STRING_ATTR_DISPLAY_NAME = "Custom String";
private static final String JSON_ATTR_TYPE_NAME = "CUSTOM_JSON_ATTRIBUTE";
private static final String JSON_ATTR_DISPLAY_NAME = "Custom Json";
private static BlackboardArtifact.Type artifactType;
private static BlackboardAttribute.Type intAttrType;
private static BlackboardAttribute.Type doubleAttrType;
@ -57,6 +59,7 @@ final class CustomArtifactType {
private static BlackboardAttribute.Type dateTimeAttrType;
private static BlackboardAttribute.Type bytesAttrType;
private static BlackboardAttribute.Type stringAttrType;
private static BlackboardAttribute.Type jsonAttrType;
/**
* Adds the custom artifact type, with its associated custom attribute
@ -73,6 +76,7 @@ final class CustomArtifactType {
dateTimeAttrType = blackboard.getOrAddAttributeType(DATETIME_ATTR_TYPE_NAME, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME, DATETIME_ATTR_DISPLAY_NAME);
bytesAttrType = blackboard.getOrAddAttributeType(BYTES_ATTR_TYPE_NAME, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE, BYTES_ATTR_DISPLAY_NAME);
stringAttrType = blackboard.getOrAddAttributeType(STRING_ATTR_TYPE_NAME, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, STRING_ATTR_DISPLAY_NAME);
jsonAttrType = blackboard.getOrAddAttributeType(JSON_ATTR_TYPE_NAME, BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON, JSON_ATTR_DISPLAY_NAME);
}
/**
@ -93,6 +97,7 @@ final class CustomArtifactType {
attributes.add(new BlackboardAttribute(dateTimeAttrType, MODULE_NAME, 60L));
attributes.add(new BlackboardAttribute(bytesAttrType, MODULE_NAME, DatatypeConverter.parseHexBinary("ABCD")));
attributes.add(new BlackboardAttribute(stringAttrType, MODULE_NAME, "Zero"));
attributes.add(new BlackboardAttribute(jsonAttrType, MODULE_NAME, "{\"fruit\": \"Apple\",\"size\": \"Large\",\"color\": \"Red\"}"));
artifact.addAttributes(attributes);
/*

View File

@ -244,6 +244,8 @@ public final class FileExporterSettingsPanel extends JPanel {
comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING.getLabel());
comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME.getLabel());
comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE.getLabel());
comboBoxValueType.addItem(BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON.getLabel());
comboBoxValueType.addItem(UNSET);
load();

View File

@ -45,6 +45,7 @@ from org.sleuthkit.datamodel import Account
from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CallMediaType
import json
import traceback
@ -181,26 +182,38 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
contactsDb.close()
## Adds a recipient to given list
def addRecipientToList(self, user_key, recipientList):
## Extracts recipeint id from 'user_key' column and adds recipient to given list,
## if the recipeint id is not the same as sender id
def addRecipientToList(self, user_key, senderId, recipientList):
if user_key is not None:
recipientId = user_key.replace('FACEBOOK:', '')
if recipientId != senderId:
recipientList.append(recipientId)
## Analyze messages
def analyzeMessages(self, dataSource, fileManager, context):
threadsDbs = AppSQLiteDB.findAppDatabases(dataSource, "threads_db2", True, self._FB_MESSENGER_PACKAGE_NAME)
for threadsDb in threadsDbs:
try:
if self.selfAccountId is not None:
threadsDBHelper = CommunicationArtifactsHelper(self.current_case.getSleuthkitCase(),
self._MODULE_NAME, threadsDb.getDBFile(),
Account.Type.FACEBOOK, Account.Type.FACEBOOK, self.selfAccountId )
## Extracts sender id from the json in 'sender' column.
def getSenderIdFromJson(self, senderJsonStr):
senderId = None;
if senderJsonStr is not None:
sender_dict = json.loads(senderJsonStr)
senderId = sender_dict['user_key']
senderId = senderId.replace('FACEBOOK:', '')
return senderId
## determines communication direction by comparing senderId with selfAccountId
def deduceDirectionFromSenderId(self, senderId):
direction = CommunicationDirection.UNKNOWN
if senderId is not None:
if senderId == self.selfAccountId:
direction = CommunicationDirection.OUTGOING
else:
threadsDBHelper = CommunicationArtifactsHelper(self.current_case.getSleuthkitCase(),
self._MODULE_NAME, threadsDb.getDBFile(),
Account.Type.FACEBOOK)
direction = CommunicationDirection.INCOMING
return direction
## Analyzes messages
def analyzeMessages(self, threadsDb, threadsDBHelper):
try:
## Messages are found in the messages table.
## This query filters messages by msg_type to only get actual user created conversation messages (msg_type 0).
@ -253,21 +266,11 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
recipientIdsList = []
## get sender id by parsing JSON in sender column
senderJsonStr = messagesResultSet.getString("sender")
if senderJsonStr is not None:
sender_dict = json.loads(senderJsonStr)
senderId = sender_dict['user_key']
senderId = senderId.replace('FACEBOOK:', '')
senderName = sender_dict['name']
fromId = senderId
if senderId == self.selfAccountId:
direction = CommunicationDirection.OUTGOING
else:
direction = CommunicationDirection.INCOMING
fromId = self.getSenderIdFromJson(messagesResultSet.getString("sender"))
direction = self.deduceDirectionFromSenderId(fromId)
# Get recipient and add to list
self.addRecipientToList(messagesResultSet.getString("user_key"),
self.addRecipientToList(messagesResultSet.getString("user_key"), fromId,
recipientIdsList)
timeStamp = messagesResultSet.getLong("timestamp_ms") / 1000
@ -284,7 +287,7 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
threadId = messagesResultSet.getString("thread_key")
else: # same msgId as last, just collect recipient from current row
self.addRecipientToList(messagesResultSet.getString("user_key"),
self.addRecipientToList(messagesResultSet.getString("user_key"), fromId,
recipientIdsList)
@ -309,6 +312,130 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
except BlackboardException as ex:
self._logger.log(Level.WARNING, "Failed to post artifacts.", ex)
self._logger.log(Level.WARNING, traceback.format_exc())
## Analyzes call logs
def analyzeCallLogs(self, threadsDb, threadsDBHelper):
try:
## Call logs are found in the messages table.
## msg_type indicates type of call:
## 9: one to one calls
## 203: group call
## 1-to-1 calls only have a call_ended record.
## group calls have a call_started_record as well as call_ended recorded, with *different* message ids.
## all the data we need can be found in the call_ended record.
sqlString = """
SELECT msg_id, text, sender, timestamp_ms, msg_type, admin_text_thread_rtc_event,
generic_admin_message_extensible_data,
messages.thread_key as thread_key,
thread_participants.user_key as user_key,
thread_users.name as name
FROM messages
JOIN thread_participants ON messages.thread_key = thread_participants.thread_key
JOIN thread_users ON thread_participants.user_key = thread_users.user_key
WHERE msg_type = 9 OR (msg_type = 203 AND admin_text_thread_rtc_event = 'group_call_ended')
ORDER BY msg_id
"""
messagesResultSet = threadsDb.runQuery(sqlString)
if messagesResultSet is not None:
oldMsgId = None
direction = CommunicationDirection.UNKNOWN
callerId = None
calleeIdsList = None
startTimeStamp = -1
endTimeStamp = -1
duration = 0
mediaType = CallMediaType.AUDIO
while messagesResultSet.next():
msgId = messagesResultSet.getString("msg_id")
# new call begins when msgId changes
if msgId != oldMsgId:
# Create call log artifact with collected attributes
if oldMsgId is not None:
messageArtifact = threadsDBHelper.addCalllog(
direction,
callerId,
calleeIdsList,
startTimeStamp,
endTimeStamp,
mediaType )
oldMsgId = msgId
# New message - collect all attributes
calleeIdsList = []
## get caller id by parsing JSON in sender column
callerId = self.getSenderIdFromJson(messagesResultSet.getString("sender"))
direction = self.deduceDirectionFromSenderId(callerId)
# Get recipient and add to list
self.addRecipientToList(messagesResultSet.getString("user_key"), callerId,
calleeIdsList)
# the timestamp from call ended msg is used as end timestamp
endTimeStamp = messagesResultSet.getLong("timestamp_ms") / 1000
# parse the generic_admin_message_extensible_data JSON to extract the duration and video fields
adminDataJsonStr = messagesResultSet.getString("generic_admin_message_extensible_data")
if adminDataJsonStr is not None:
adminData_dict = json.loads(adminDataJsonStr)
duration = adminData_dict['call_duration'] # call duration in seconds
isVideo = adminData_dict['video']
if isVideo:
mediaType = CallMediaType.VIDEO
startTimeStamp = endTimeStamp - duration
else: # same msgId as last, just collect callee from current row
self.addRecipientToList(messagesResultSet.getString("user_key"), callerId,
calleeIdsList)
# at the end of the loop, add last message
messageArtifact = threadsDBHelper.addCalllog(
direction,
callerId,
calleeIdsList,
startTimeStamp,
endTimeStamp,
mediaType )
except SQLException as ex:
self._logger.log(Level.WARNING, "Error processing query result for FB Messenger call logs.", ex)
self._logger.log(Level.WARNING, traceback.format_exc())
except TskCoreException as ex:
self._logger.log(Level.SEVERE, "Failed to add FB Messenger call log artifacts.", ex)
self._logger.log(Level.SEVERE, traceback.format_exc())
except BlackboardException as ex:
self._logger.log(Level.WARNING, "Failed to post FB Messenger call log artifacts.", ex)
self._logger.log(Level.WARNING, traceback.format_exc())
## Analyze messages and call log threads
def analyzeMessagesAndCallLogs(self, dataSource, fileManager, context):
threadsDbs = AppSQLiteDB.findAppDatabases(dataSource, "threads_db2", True, self._FB_MESSENGER_PACKAGE_NAME)
for threadsDb in threadsDbs:
try:
if self.selfAccountId is not None:
threadsDBHelper = CommunicationArtifactsHelper(self.current_case.getSleuthkitCase(),
self._MODULE_NAME, threadsDb.getDBFile(),
Account.Type.FACEBOOK, Account.Type.FACEBOOK, self.selfAccountId )
else:
threadsDBHelper = CommunicationArtifactsHelper(self.current_case.getSleuthkitCase(),
self._MODULE_NAME, threadsDb.getDBFile(),
Account.Type.FACEBOOK)
self.analyzeMessages(threadsDb, threadsDBHelper)
self.analyzeCallLogs(threadsDb, threadsDBHelper)
except TskCoreException as ex:
self._logger.log(Level.SEVERE, "Failed to to create CommunicationArtifactsHelper for FB Messenger.", ex)
self._logger.log(Level.SEVERE, traceback.format_exc())
finally:
threadsDb.close()
@ -321,6 +448,6 @@ class FBMessengerAnalyzer(general.AndroidComponentAnalyzer):
return
self.analyzeContacts(dataSource, fileManager, context)
self.analyzeMessages(dataSource, fileManager, context)
self.analyzeMessagesAndCallLogs(dataSource, fileManager, context)

View File

@ -43,10 +43,14 @@ from org.sleuthkit.datamodel import Content
from org.sleuthkit.datamodel import TskCoreException
from org.sleuthkit.datamodel.Blackboard import BlackboardException
from org.sleuthkit.datamodel import Account
from org.sleuthkit.datamodel.blackboardutils import FileAttachment
from org.sleuthkit.datamodel.blackboardutils import URLAttachment
from org.sleuthkit.datamodel.blackboardutils import MessageAttachments
from org.sleuthkit.datamodel.blackboardutils import CommunicationArtifactsHelper
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import MessageReadStatus
from org.sleuthkit.datamodel.blackboardutils.CommunicationArtifactsHelper import CommunicationDirection
import json
import traceback
import general
@ -66,6 +70,8 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer):
-- A messages table which stores the message details
--- sender/receiver buid, timestamp, message_type (1: incoming, 0: outgoing), message_read...
--- 'imdata' column stores a json structure with all the message details, including attachments
---- attachment file path may be specified in local_path or original_path. Original path, if available is a better candidate.
---- For sent files, files seem to get uploaded to IMO Servers. There is no URL available in the imdata though.
"""
@ -156,7 +162,7 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer):
msgReadStatus = MessageReadStatus.UNKNOWN
timeStamp = messagesResultSet.getLong("timestamp") / 1000000000
msgBody = messagesResultSet.getString("last_message")
messageArtifact = friendsDBHelper.addMessage(
self._MESSAGE_TYPE,
@ -166,12 +172,34 @@ class IMOAnalyzer(general.AndroidComponentAnalyzer):
timeStamp,
msgReadStatus,
"", # subject
messagesResultSet.getString("last_message"),
msgBody,
"") # thread id
# TBD: parse the imdata JSON structure to figure out if there is an attachment.
# If one exists, add the attachment as a derived file and a child of the message artifact.
# Parse the imdata JSON structure to check if there is an attachment.
# If one exists, create an attachment and add to the message.
fileAttachments = ArrayList()
urlAttachments = ArrayList()
imdataJsonStr = messagesResultSet.getString("imdata")
if imdataJsonStr is not None:
imdata_dict = json.loads(imdataJsonStr)
# set to none if the key doesn't exist in the dict
attachmentOriginalPath = imdata_dict.get('original_path', None)
attachmentLocalPath = imdata_dict.get('local_path', None)
if attachmentOriginalPath:
attachmentPath = attachmentOriginalPath
else:
attachmentPath = attachmentLocalPath
if attachmentPath:
# Create a file attachment with given path
fileAttachment = FileAttachment(current_case.getSleuthkitCase(), friendsDb.getDBFile().getDataSource(), attachmentPath)
fileAttachments.add(fileAttachment)
msgAttachments = MessageAttachments(fileAttachments, [])
attachmentArtifact = friendsDBHelper.addAttachments(messageArtifact, msgAttachments)
except SQLException as ex:
self._logger.log(Level.WARNING, "Error processing query result for IMO friends", ex)

12
travis_build.sh Normal file
View File

@ -0,0 +1,12 @@
#!/bin/bash
set -e
echo "Building TSK..."
cd sleuthkit/sleuthkit
./bootstrap && configure --prefix=/usr && make
pushd bindings/java && ant -q dist-PostgreSQL && popd
echo "Building Autopsy..." && echo -en 'travis_fold:start:script.build\\r'
cd $TRAVIS_BUILD_DIR/
ant build
echo -en 'travis_fold:end:script.build\\r'