Merge pull request #5819 from gdicristofaro/6113-gpxFileIngest

6113 gpx file ingest
This commit is contained in:
Richard Cordovano 2020-04-17 15:42:46 -04:00 committed by GitHub
commit 09167a1b42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -44,7 +44,6 @@ from org.sleuthkit.datamodel.blackboardutils.attributes.GeoTrackPoints import Tr
from org.sleuthkit.autopsy.datamodel import ContentUtils
from org.sleuthkit.autopsy.ingest import IngestModule
from org.sleuthkit.autopsy.ingest.IngestModule import IngestModuleException
from org.sleuthkit.autopsy.ingest import DataSourceIngestModule
from org.sleuthkit.autopsy.ingest import FileIngestModule
from org.sleuthkit.autopsy.ingest import IngestModuleFactoryAdapter
from org.sleuthkit.autopsy.ingest import IngestMessage
@ -60,9 +59,14 @@ import gpxpy
import gpxpy.gpx
import gpxpy.parser
# to get a random filename to prevent race conditions
import uuid
# Factory that defines the name and details of the module and allows Autopsy
# to create instances of the modules that will do the analysis.
class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
class GPXParserFileIngestModuleFactory(IngestModuleFactoryAdapter):
moduleName = "GPX Parser"
@ -75,158 +79,176 @@ class GPXParserDataSourceIngestModuleFactory(IngestModuleFactoryAdapter):
def getModuleVersionNumber(self):
return "1.2"
def isDataSourceIngestModuleFactory(self):
def isFileIngestModuleFactory(self):
return True
def createDataSourceIngestModule(self, ingestOptions):
return GPXParserDataSourceIngestModule()
def createFileIngestModule(self, ingestOptions):
return GPXParserFileIngestModule()
# Data Source-level ingest module. One gets created per data source.
class GPXParserDataSourceIngestModule(DataSourceIngestModule):
# File level ingest module.
class GPXParserFileIngestModule(FileIngestModule):
logger = Logger.getLogger(GPXParserDataSourceIngestModuleFactory.moduleName)
logger = Logger.getLogger(
GPXParserFileIngestModuleFactory.moduleName)
writeDebugMsgs = False
def log(self, level, msg):
self.logger.logp(level, self.__class__.__name__, inspect.stack()[1][3], msg)
self.logger.logp(level, self.__class__.__name__,
inspect.stack()[1][3], msg)
def __init__(self):
self.context = None
# Where any setup and configuration is done.
def startUp(self, context):
self.context = context
# Where the analysis is done.
def process(self, dataSource, progressBar):
# We don't know how much work there is yet.
progressBar.switchToIndeterminate()
# Get the case database and its blackboard.
skCase = Case.getCurrentCase().getSleuthkitCase()
blackboard = skCase.getBlackboard()
# Get any files with a .gpx extension.
# It would perhaps be better to get these files by MIME type instead.
# RC: It would also be better if this were a file level ingest module so it could process files extracted from archives.
fileManager = Case.getCurrentCase().getServices().getFileManager()
files = fileManager.findFiles(dataSource, "%.gpx")
# Update the progress bar now that we know how much work there is to do.
numFiles = len(files)
if self.writeDebugMsgs: self.log(Level.INFO, "Found " + str(numFiles) + " GPX files")
progressBar.switchToDeterminate(numFiles)
self.fileCount = 0
# Get the module name, it will be needed for adding attributes
moduleName = GPXParserDataSourceIngestModuleFactory.moduleName
self.moduleName = GPXParserFileIngestModuleFactory.moduleName
# Get the case database and its blackboard.
self.skCase = Case.getCurrentCase().getSleuthkitCase()
self.blackboard = self.skCase.getBlackboard()
# Check if a folder for this module is present in the case Temp directory.
# If not, create it.
dirName = os.path.join(Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module")
self.dirName = os.path.join(
Case.getCurrentCase().getTempDirectory(), "GPX_Parser_Module")
try:
os.stat(dirName)
os.stat(self.dirName)
except:
os.mkdir(dirName)
os.mkdir(self.dirName)
# Where any setup and configuration is done.
def startUp(self, context):
self.context = context
self.fileCount = 0
# Where the file analysis is done.
def process(self, file):
if not file.getName().lower().endswith(".gpx"):
return IngestModule.ProcessResult.OK
# Create a temp file name. It appears that we cannot close and delete
# this file, but we can overwrite it for each file we need to process.
fileName = os.path.join(dirName, "tmp.gpx")
fileName = os.path.join(self.dirName, uuid.uuid4().hex + ".gpx")
fileCount = 0;
for file in files:
# Create a GeoArtifactsHelper for this file.
geoArtifactHelper = GeoArtifactsHelper(
self.skCase, self.moduleName, None, file)
# Create a GeoArtifactsHelper for this file.
geoArtifactHelper = GeoArtifactsHelper(skCase, moduleName, None, file)
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing " + file.getUniquePath() +
" (objID = " + str(file.getId()) + ")")
# Check if the user pressed cancel while we were busy.
if self.context.isJobCancelled():
return IngestModule.ProcessResult.OK
# Write the file so that it can be parsed by gpxpy.
localFile = File(fileName)
ContentUtils.writeToFile(file, localFile)
if self.writeDebugMsgs: self.log(Level.INFO, "Processing " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
fileCount += 1
# Send the file to gpxpy for parsing.
gpxfile = open(fileName)
try:
gpx = gpxpy.parse(gpxfile)
if self.writeDebugMsgs:
self.log(Level.INFO, "Parsed " + file.getUniquePath() +
" (objID = " + str(file.getId()) + ")")
except Exception as e:
self.log(Level.WARNING, "Error parsing file " + file.getUniquePath() +
" (objID = " + str(file.getId()) + "):" + str(e))
return IngestModule.ProcessResult.ERROR
# Write the file so that it can be parsed by gpxpy.
localFile = File(fileName)
ContentUtils.writeToFile(file, localFile)
if gpx:
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing tracks from " +
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
# Send the file to gpxpy for parsing.
gpxfile = open(fileName)
try:
gpx = gpxpy.parse(gpxfile)
if self.writeDebugMsgs: self.log(Level.INFO, "Parsed " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
except Exception as e:
self.log(Level.WARNING, "Error parsing file " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
continue
for track in gpx.tracks:
for segment in track.segments:
geoPointList = GeoTrackPoints()
for point in segment.points:
if gpx:
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 = GeoTrackPoints()
for point in segment.points:
elevation = 0
if point.elevation != None:
elevation = point.elevation
timeStamp = 0
try:
if (point.time != None):
timeStamp = long(time.mktime(point.time.timetuple()))
except Exception as e:
self.log(Level.WARNING, "Error getting track timestamp from " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
geoPointList.addPoint(TrackPoint(point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
elevation = 0
if point.elevation != None:
elevation = point.elevation
timeStamp = 0
try:
geoArtifactHelper.addTrack("Track", geoPointList, None)
except Blackboard.BlackboardException as e:
self.log(Level.SEVERE, "Error posting GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS track artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
if (point.time != None):
timeStamp = long(time.mktime(
point.time.timetuple()))
except Exception as e:
self.log(Level.WARNING, "Error getting track timestamp from " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + str(e))
if self.writeDebugMsgs: self.log(Level.INFO, "Processing waypoints from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
for waypoint in gpx.waypoints:
geoPointList.addPoint(TrackPoint(
point.latitude, point.longitude, elevation, None, 0, 0, 0, timeStamp))
try:
art = file.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
attributes = ArrayList()
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), moduleName, waypoint.latitude))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), moduleName, waypoint.longitude))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG.getTypeID(), moduleName, "Waypoint"))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), moduleName, waypoint.name))
attributes.add(BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), moduleName, "GPXParser"))
art.addAttributes(attributes)
blackboard.postArtifact(art, moduleName)
geoArtifactHelper.addTrack("Track", geoPointList, None)
except Blackboard.BlackboardException as e:
self.log(Level.SEVERE, "Error posting GPS bookmark artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
self.log(Level.SEVERE, "Error posting GPS track artifact for " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS bookmark artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
self.log(Level.SEVERE, "Error creating GPS track artifact for " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
if self.writeDebugMsgs: self.log(Level.INFO, "Processing routes from " + file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
for route in gpx.routes:
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing waypoints from " +
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
geoWaypoints = GeoWaypoints()
for waypoint in gpx.waypoints:
for point in route.points:
geoWaypoints.addPoint(Waypoint(point.latitude, point.longitude, point.elevation, point.name))
try:
art = file.newArtifact(
BlackboardArtifact.ARTIFACT_TYPE.TSK_GPS_BOOKMARK)
try:
geoArtifactHelper.addRoute(None, None, geoWaypoints, None)
except Blackboard.BlackboardException as e:
self.log("Error posting GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS route artifact for " + file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
attributes = ArrayList()
attributes.add(BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LATITUDE.getTypeID(), self.moduleName, waypoint.latitude))
attributes.add(BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE.getTypeID(), self.moduleName, waypoint.longitude))
attributes.add(BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FLAG.getTypeID(), self.moduleName, "Waypoint"))
attributes.add(BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME.getTypeID(), self.moduleName, waypoint.name))
attributes.add(BlackboardAttribute(
BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PROG_NAME.getTypeID(), self.moduleName, "GPXParser"))
art.addAttributes(attributes)
# Update the progress bar.
progressBar.progress(fileCount)
self.blackboard.postArtifact(art, self.moduleName)
# Post a message to the ingest messages inbox.
message = IngestMessage.createMessage(IngestMessage.MessageType.DATA, moduleName, "Processed %d files" % fileCount)
IngestServices.getInstance().postMessage(message)
return IngestModule.ProcessResult.OK;
except Blackboard.BlackboardException as e:
self.log(Level.SEVERE, "Error posting GPS bookmark artifact for " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS bookmark artifact for " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
if self.writeDebugMsgs:
self.log(Level.INFO, "Processing routes from " +
file.getUniquePath() + " (objID = " + str(file.getId()) + ")")
for route in gpx.routes:
geoWaypoints = GeoWaypoints()
for point in route.points:
geoWaypoints.addPoint(
Waypoint(point.latitude, point.longitude, point.elevation, point.name))
try:
geoArtifactHelper.addRoute(None, None, geoWaypoints, None)
except Blackboard.BlackboardException as e:
self.log("Error posting GPS route artifact for " + file.getUniquePath() +
" (objID = " + str(file.getId()) + "):" + e.getMessage())
except TskCoreException as e:
self.log(Level.SEVERE, "Error creating GPS route artifact for " +
file.getUniquePath() + " (objID = " + str(file.getId()) + "):" + e.getMessage())
self.fileCount += 1
return IngestModule.ProcessResult.OK
def shutDown(self):
message = IngestMessage.createMessage(
IngestMessage.MessageType.DATA, GPXParserFileIngestModuleFactory.moduleName,
str(self.fileCount) + " files found")
ingestServices = IngestServices.getInstance().postMessage(message)