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;
 
   56 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   60 import org.
sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
 
   63 import org.
sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
 
   71     "CannotRunFileTypeDetection=Cannot run file type detection." 
   77     private final AtomicInteger filesProcessed = 
new AtomicInteger(0);
 
   78     private volatile boolean filesToFire = 
false;
 
   79     private final List<BlackboardArtifact> listOfFacesDetectedArtifacts = 
new ArrayList<>();
 
   83     private final HashSet<String> supportedMimeTypes = 
new HashSet<>();
 
   84     private TimeZone timeZone = null;
 
   88         supportedMimeTypes.add(
"audio/x-wav"); 
 
   89         supportedMimeTypes.add(
"image/jpeg"); 
 
   90         supportedMimeTypes.add(
"image/tiff"); 
 
   95         jobId = context.getJobId();
 
  109             logger.log(Level.INFO, 
"Exception while getting open case.", ex); 
 
  113         if ((content.getType().equals(TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS)
 
  114                 || (content.getType().equals(TSK_DB_FILES_TYPE_ENUM.SLACK)))) {
 
  118         if (content.isFile() == 
false) {
 
  123         if (content.getKnown().equals(TskData.FileKnown.KNOWN)) {
 
  128         final int filesProcessedValue = filesProcessed.incrementAndGet();
 
  129         if ((filesProcessedValue % 1000 == 0)) {
 
  137         if (!parsableFormat(content)) {
 
  141         return processFile(content);
 
  144     @Messages({
"ExifParserFileIngestModule.indexError.message=Failed to index EXIF Metadata artifact for keyword search."})
 
  145     ProcessResult processFile(AbstractFile f) {
 
  146         InputStream in = null;
 
  147         BufferedInputStream bin = null;
 
  150             in = 
new ReadContentInputStream(f);
 
  151             bin = 
new BufferedInputStream(in);
 
  153             Collection<BlackboardAttribute> attributes = 
new ArrayList<>();
 
  154             Metadata metadata = ImageMetadataReader.readMetadata(bin);
 
  157             ExifSubIFDDirectory exifDir = metadata.getFirstDirectoryOfType(ExifSubIFDDirectory.class);
 
  158             if (exifDir != null) {
 
  161                 if (timeZone == null) {
 
  163                         Content dataSource = f.getDataSource();
 
  164                         if ((dataSource != null) && (dataSource instanceof Image)) {
 
  165                             Image image = (Image) dataSource;
 
  166                             timeZone = TimeZone.getTimeZone(image.getTimeZone());
 
  168                     } 
catch (TskCoreException ex) {
 
  169                         logger.log(Level.INFO, 
"Error getting time zones", ex); 
 
  172                 Date date = exifDir.getDate(ExifSubIFDDirectory.TAG_DATETIME_ORIGINAL, timeZone);
 
  174                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_CREATED, ExifParserModuleFactory.getModuleName(), date.getTime() / 1000));
 
  179             GpsDirectory gpsDir = metadata.getFirstDirectoryOfType(GpsDirectory.class);
 
  180             if (gpsDir != null) {
 
  181                 GeoLocation loc = gpsDir.getGeoLocation();
 
  183                     double latitude = loc.getLatitude();
 
  184                     double longitude = loc.getLongitude();
 
  185                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LATITUDE, ExifParserModuleFactory.getModuleName(), latitude));
 
  186                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_LONGITUDE, ExifParserModuleFactory.getModuleName(), longitude));
 
  189                 Rational altitude = gpsDir.getRational(GpsDirectory.TAG_ALTITUDE);
 
  190                 if (altitude != null) {
 
  191                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_GEO_ALTITUDE, ExifParserModuleFactory.getModuleName(), altitude.doubleValue()));
 
  196             ExifIFD0Directory devDir = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
 
  197             if (devDir != null) {
 
  198                 String model = devDir.getString(ExifIFD0Directory.TAG_MODEL);
 
  199                 if (model != null && !model.isEmpty()) {
 
  200                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MODEL, ExifParserModuleFactory.getModuleName(), model));
 
  203                 String make = devDir.getString(ExifIFD0Directory.TAG_MAKE);
 
  204                 if (make != null && !make.isEmpty()) {
 
  205                     attributes.add(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DEVICE_MAKE, ExifParserModuleFactory.getModuleName(), make));
 
  210             if (!attributes.isEmpty()) {
 
  211                 BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_METADATA_EXIF);
 
  212                 bba.addAttributes(attributes);
 
  217                 } 
catch (Blackboard.BlackboardException ex) {
 
  218                     logger.log(Level.SEVERE, 
"Unable to index blackboard artifact " + bba.getArtifactID(), ex); 
 
  219                     MessageNotifyUtil.Notify.error(
 
  220                             Bundle.ExifParserFileIngestModule_indexError_message(), bba.getDisplayName());
 
  225             return ProcessResult.OK;
 
  226         } 
catch (TskCoreException ex) {
 
  227             logger.log(Level.WARNING, 
"Failed to create blackboard artifact for exif metadata ({0}).", ex.getLocalizedMessage()); 
 
  228             return ProcessResult.ERROR;
 
  229         } 
catch (ImageProcessingException ex) {
 
  230             logger.log(Level.WARNING, String.format(
"Failed to process the image file '%s/%s' (id=%d).", f.getParentPath(), f.getName(), f.getId()), ex);
 
  231             return ProcessResult.ERROR;
 
  232         } 
catch (ReadContentInputStreamException ex) {
 
  233             logger.log(Level.WARNING, String.format(
"Error while trying to read image file '%s/%s' (id=%d).", f.getParentPath(), f.getName(), f.getId()), ex); 
 
  234             return ProcessResult.ERROR;
 
  235         } 
catch (IOException ex) {
 
  236             logger.log(Level.WARNING, String.format(
"IOException when parsing image file '%s/%s' (id=%d).", f.getParentPath(), f.getName(), f.getId()), ex); 
 
  237             return ProcessResult.ERROR;
 
  246             } 
catch (IOException ex) {
 
  247                 logger.log(Level.WARNING, 
"Failed to close InputStream.", ex); 
 
  248                 return ProcessResult.ERROR;
 
  263         return supportedMimeTypes.contains(mimeType);
 
synchronized long decrementAndGet(long jobId)
 
void startUp(IngestJobContext context)
 
static Case getOpenCase()
 
ProcessResult process(AbstractFile content)
 
synchronized long incrementAndGet(long jobId)
 
String getMIMEType(AbstractFile file)
 
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
 
Blackboard getBlackboard()
 
synchronized void indexArtifact(BlackboardArtifact artifact)
 
synchronized static Logger getLogger(String name)
 
FileTypeDetector fileTypeDetector
 
boolean parsableFormat(AbstractFile f)
 
static synchronized IngestServices getInstance()