19 package org.sleuthkit.autopsy.modules.exif;
 
   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.io.InputStream;
 
   32 import java.util.ArrayList;
 
   33 import java.util.Collection;
 
   34 import java.util.Date;
 
   35 import java.util.HashSet;
 
   36 import java.util.List;
 
   37 import java.util.TimeZone;
 
   38 import java.util.concurrent.atomic.AtomicInteger;
 
   39 import java.util.logging.Level;
 
   40 import org.openide.util.NbBundle;
 
   41 import org.openide.util.NbBundle.Messages;
 
   55 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   61 import org.
sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
 
   69     "CannotRunFileTypeDetection=Cannot run file type detection." 
   75     private final AtomicInteger filesProcessed = 
new AtomicInteger(0);
 
   76     private volatile boolean filesToFire = 
false;
 
   77     private final List<BlackboardArtifact> listOfFacesDetectedArtifacts = 
new ArrayList<>();
 
   81     private final HashSet<String> supportedMimeTypes = 
new HashSet<>();
 
   82     private TimeZone timeZone = null;
 
   86         supportedMimeTypes.add(
"audio/x-wav"); 
 
   87         supportedMimeTypes.add(
"image/jpeg"); 
 
   88         supportedMimeTypes.add(
"image/tiff"); 
 
   93         jobId = context.getJobId();
 
  107         if ((content.getType().equals(TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS) ||
 
  108                 (content.getType().equals(TSK_DB_FILES_TYPE_ENUM.SLACK)))) {
 
  112         if (content.isFile() == 
false) {
 
  117         if (content.getKnown().equals(TskData.FileKnown.KNOWN)) {
 
  122         final int filesProcessedValue = filesProcessed.incrementAndGet();
 
  123         if ((filesProcessedValue % 1000 == 0)) {
 
  131         if (!parsableFormat(content)) {
 
  135         return processFile(content);
 
  138     @Messages({
"ExifParserFileIngestModule.indexError.message=Failed to index EXIF Metadata artifact for keyword search."})
 
  139     ProcessResult processFile(AbstractFile f) {
 
  140         InputStream in = null;
 
  141         BufferedInputStream bin = null;
 
  144             in = 
new ReadContentInputStream(f);
 
  145             bin = 
new BufferedInputStream(in);
 
  147             Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  148             Metadata metadata = ImageMetadataReader.readMetadata(bin);
 
  151             ExifSubIFDDirectory exifDir = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
 
  152             if (exifDir != null) {
 
  155                 if (timeZone == null) {
 
  157                         Content dataSource = f.getDataSource();
 
  158                         if ((dataSource != null) && (dataSource instanceof Image)) {
 
  159                             Image image = (Image) dataSource;
 
  160                             timeZone = TimeZone.getTimeZone(image.getTimeZone());
 
  162                     } 
catch (TskCoreException ex) {
 
  163                         logger.log(Level.INFO, 
"Error getting time zones", ex); 
 
  166                 Date date = exifDir.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL, timeZone);
 
  168                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, ExifParserModuleFactory.getModuleName(), date.getTime() / 1000));
 
  173             GpsDirectory gpsDir = metadata.getFirstDirectoryOfType(GpsDirectory.class);
 
  174             if (gpsDir != null) {
 
  175                 GeoLocation loc = gpsDir.getGeoLocation();
 
  177                     double latitude = loc.getLatitude();
 
  178                     double longitude = loc.getLongitude();
 
  179                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, ExifParserModuleFactory.getModuleName(), latitude));
 
  180                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, ExifParserModuleFactory.getModuleName(), longitude));
 
  183                 Rational altitude = gpsDir.getRational(GpsDirectory.TAG_ALTITUDE);
 
  184                 if (altitude != null) {
 
  185                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE, ExifParserModuleFactory.getModuleName(), altitude.doubleValue()));
 
  190             ExifIFD0Directory devDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
 
  191             if (devDir != null) {
 
  192                 String model = devDir.getString(ExifIFD0Directory.TAG_MODEL);
 
  193                 if (model != null && !model.isEmpty()) {
 
  194                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, ExifParserModuleFactory.getModuleName(), model));
 
  197                 String make = devDir.getString(ExifIFD0Directory.TAG_MAKE);
 
  198                 if (make != null && !make.isEmpty()) {
 
  199                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, ExifParserModuleFactory.getModuleName(), make));
 
  204             if (!attributes.isEmpty()) {
 
  205                 BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF);
 
  206                 bba.addAttributes(attributes);
 
  211                 } 
catch (Blackboard.BlackboardException ex) {
 
  212                     logger.log(Level.SEVERE, 
"Unable to index blackboard artifact " + bba.getArtifactID(), ex); 
 
  213                     MessageNotifyUtil.Notify.error(
 
  214                             Bundle.ExifParserFileIngestModule_indexError_message(), bba.getDisplayName());
 
  219             return ProcessResult.OK;
 
  220         } 
catch (TskCoreException ex) {
 
  221             logger.log(Level.WARNING, 
"Failed to create blackboard artifact for exif metadata ({0}).", ex.getLocalizedMessage()); 
 
  222             return ProcessResult.ERROR;
 
  223         } 
catch (ImageProcessingException ex) {
 
  224             logger.log(Level.WARNING, 
"Failed to process the image file: {0}/{1}({2})", 
new Object[]{f.getParentPath(), f.getName(), ex.getLocalizedMessage()}); 
 
  225             return ProcessResult.ERROR;
 
  226         } 
catch (IOException ex) {
 
  227             logger.log(Level.WARNING, 
"IOException when parsing image file: " + f.getParentPath() + 
"/" + f.getName(), ex); 
 
  228             return ProcessResult.ERROR;
 
  237             } 
catch (IOException ex) {
 
  238                 logger.log(Level.WARNING, 
"Failed to close InputStream.", ex); 
 
  239                 return ProcessResult.ERROR;
 
  255             if (mimeType != null) {
 
  256                 return supportedMimeTypes.contains(mimeType);
 
  260         } 
catch (TskCoreException ex) {
 
  261             logger.log(Level.SEVERE, 
"Failed to detect file type", ex); 
 
synchronized long decrementAndGet(long jobId)
void startUp(IngestJobContext context)
ProcessResult process(AbstractFile content)
synchronized long incrementAndGet(long jobId)
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
Blackboard getBlackboard()
synchronized void indexArtifact(BlackboardArtifact artifact)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
FileTypeDetector fileTypeDetector
String getFileType(AbstractFile file)
boolean parsableFormat(AbstractFile f)
static synchronized IngestServices getInstance()