19 package org.sleuthkit.autopsy.modules.pictureanalyzer.impls;
21 import com.drew.imaging.ImageMetadataReader;
22 import com.drew.imaging.ImageProcessingException;
23 import com.drew.lang.GeoLocation;
24 import com.drew.lang.Rational;
25 import com.drew.metadata.Metadata;
26 import com.drew.metadata.exif.ExifIFD0Directory;
27 import com.drew.metadata.exif.ExifSubIFDDirectory;
28 import com.drew.metadata.exif.GpsDirectory;
29 import java.io.BufferedInputStream;
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.Arrays;
33 import java.util.Collection;
34 import java.util.Date;
36 import java.util.HashSet;
37 import java.util.TimeZone;
38 import java.util.logging.Level;
39 import org.apache.commons.lang3.StringUtils;
40 import org.openide.util.NbBundle;
41 import org.openide.util.lookup.ServiceProvider;
51 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF;
52 import static org.
sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED;
54 import static org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
75 "ExifProcessor.indexError.message=Failed to post EXIF Metadata artifact(s).",
76 "ExifProcessor.userContent.description=EXIF metadata data exists for this file."
81 try (BufferedInputStream bin =
new BufferedInputStream(
new ReadContentInputStream(file));) {
83 final Collection<BlackboardAttribute> attributes =
new ArrayList<>();
84 final Metadata metadata = ImageMetadataReader.readMetadata(bin);
87 final ExifSubIFDDirectory exifDir = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
88 if (exifDir != null) {
91 TimeZone timeZone = null;
93 Content dataSource = file.getDataSource();
94 if ((dataSource != null) && (dataSource instanceof Image)) {
95 Image image = (Image) dataSource;
96 timeZone = TimeZone.getTimeZone(image.getTimeZone());
98 }
catch (TskCoreException ex) {
99 logger.log(Level.INFO,
"Error getting time zones", ex);
102 final Date date = exifDir.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL, timeZone);
104 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, MODULE_NAME, date.getTime() / 1000));
113 final GpsDirectory gpsDir = metadata.getFirstDirectoryOfType(GpsDirectory.class);
114 if (gpsDir != null) {
115 final GeoLocation loc = gpsDir.getGeoLocation();
117 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, MODULE_NAME, loc.getLatitude()));
118 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, MODULE_NAME, loc.getLongitude()));
121 final Rational altitude = gpsDir.getRational(GpsDirectory.TAG_ALTITUDE);
122 if (altitude != null) {
123 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE, MODULE_NAME, altitude.doubleValue()));
132 final ExifIFD0Directory devDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
133 if (devDir != null) {
134 final String model = devDir.getString(ExifIFD0Directory.TAG_MODEL);
135 if (StringUtils.isNotBlank(model)) {
136 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, MODULE_NAME, model));
139 final String make = devDir.getString(ExifIFD0Directory.TAG_MAKE);
140 if (StringUtils.isNotBlank(make)) {
141 attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, MODULE_NAME, make));
151 if (!attributes.isEmpty() && !blackboard.artifactExists(file, TSK_METADATA_EXIF, attributes)) {
153 final BlackboardArtifact exifArtifact = file.newDataArtifact(
new BlackboardArtifact.Type(TSK_METADATA_EXIF), attributes);
155 final BlackboardArtifact userSuspectedArtifact = file.newAnalysisResult(
156 BlackboardArtifact.Type.TSK_USER_CONTENT_SUSPECTED, Score.SCORE_UNKNOWN, null, null, null,
157 Arrays.asList(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, MODULE_NAME, Bundle.ExifProcessor_userContent_description())))
158 .getAnalysisResult();
162 blackboard.postArtifact(exifArtifact, MODULE_NAME);
163 blackboard.postArtifact(userSuspectedArtifact, MODULE_NAME);
164 }
catch (Blackboard.BlackboardException ex) {
165 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + exifArtifact.getArtifactID(), ex);
167 Bundle.ExifProcessor_indexError_message(), exifArtifact.getDisplayName());
170 }
catch (TskCoreException ex) {
171 logger.log(Level.WARNING,
"Failed to create blackboard artifact for "
172 +
"exif metadata ({0}).", ex.getLocalizedMessage());
173 }
catch (IOException | ImageProcessingException unused) {
175 logger.log(Level.WARNING, String.format(
"Error parsing "
176 +
"image file '%s/%s' (id=%d).", file.getParentPath(), file.getName(), file.getId()));
178 logger.log(Level.INFO,
"Exception while getting open case.", ex);
184 return new HashSet<String>() {
void process(IngestJobContext context, AbstractFile file)
static String getModuleName()
SleuthkitCase getSleuthkitCase()
boolean fileIngestIsCancelled()
static void error(String title, String message)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
Set< String > mimeTypes()