From beb8efaa6abb89b76509fe29df7092b501fb599e Mon Sep 17 00:00:00 2001 From: jmillman Date: Mon, 29 Jun 2015 12:22:26 -0400 Subject: [PATCH] Extract FileTypeUtils from ImageGalleryModule remove FileTypeIcons remove deprecated method from GroupManager --- .../autopsy/imagegallery/FileTypeIcons.java | 106 ------------ .../autopsy/imagegallery/FileTypeUtils.java | 161 ++++++++++++++++++ .../imagegallery/ImageGalleryController.java | 123 +++++++------ .../imagegallery/ImageGalleryModule.java | 83 +-------- .../imagegallery/datamodel/DrawableDB.java | 4 +- .../imagegallery/datamodel/DrawableFile.java | 5 +- .../imagegallery/datamodel/VideoFile.java | 9 +- .../datamodel/grouping/GroupManager.java | 59 ------- 8 files changed, 248 insertions(+), 302 deletions(-) delete mode 100644 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeIcons.java create mode 100644 ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeIcons.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeIcons.java deleted file mode 100644 index 18beb476c6..0000000000 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeIcons.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Autopsy Forensic Browser - * - * Copyright 2015 Basis Technology Corp. - * Contact: carrier sleuthkit org - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.sleuthkit.autopsy.imagegallery; - -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.LoadingCache; -import java.net.URL; -import java.util.Objects; -import java.util.logging.Level; -import javafx.scene.image.Image; -import org.apache.commons.lang3.StringUtils; -import org.apache.tika.mime.MimeType; -import org.apache.tika.mime.MimeTypeException; -import org.apache.tika.mime.MimeTypes; -import org.openide.util.Exceptions; -import org.sleuthkit.autopsy.coreutils.Logger; -import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; -import org.sleuthkit.autopsy.imagegallery.datamodel.ImageFile; -import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; -import org.sleuthkit.datamodel.TskCoreException; - -/** - * - */ -public class FileTypeIcons { - - private static final Image VIDEO_ICON = new Image("org/sleuthkit/autopsy/imagegallery/images/Clapperboard.png"); - private static final Image IMAGE_ICON = new Image("org/sleuthkit/autopsy/imagegallery/images/Clapperboard.png"); - - public static Image getGenericVideoThumbnail() { - return VIDEO_ICON; - } - - private Image getGenericImageIcon() { - return IMAGE_ICON; - } - static private FileTypeIcons instance; - - static public synchronized FileTypeIcons FileTypeIconsgetInstance() { - if (Objects.isNull(instance)) { - instance = new FileTypeIcons(); - } - - return instance; - } - - private final LoadingCache iconCache = CacheBuilder.newBuilder().build(CacheLoader.from(this::getImageForMimeType)); - - Image getImageForMimeType(String mimeType) { - try { - final MimeType forName = MimeTypes.getDefaultMimeTypes().forName(mimeType); - for (String extension : forName.getExtensions()) { - final URL iconURL = ImageFile.class.getResource("/org/sleuthkit/autopsy/imagegallery/images/mimeTypes/" - + StringUtils.strip(extension, ".") + "-icon-16x16.png"); - if (Objects.isNull(iconURL)) { - return new Image(iconURL.toExternalForm(), true); - } - } - } catch (MimeTypeException ex) { - Logger.getLogger(FileTypeIcons.class.getName()).log(Level.WARNING, "Failed to get MimeType for " + mimeType); - } - return null; - } - - Image getFileTypeIcon(DrawableFile file) { - if (Objects.nonNull(fileTypeDetector)) { - try { - String fileType1 = fileTypeDetector.getFileType(file.getAbstractFile()); - return iconCache.getUnchecked(fileType1); - } catch (TskCoreException ex) { - Logger.getLogger(FileTypeIcons.class.getName()).log(Level.WARNING, "Failed to get file type for " + file.getName()); - } - } - - return file.isVideo() ? getGenericVideoThumbnail() : getGenericImageIcon(); - } - private final FileTypeDetector fileTypeDetector; - - private FileTypeIcons() { - FileTypeDetector ftd = null; - try { - ftd = new FileTypeDetector(); - } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - Exceptions.printStackTrace(ex); - } - fileTypeDetector = ftd; - } - -} diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java new file mode 100644 index 0000000000..3955f8f4b0 --- /dev/null +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/FileTypeUtils.java @@ -0,0 +1,161 @@ +/* + * Autopsy Forensic Browser + * + * Copyright 2015 Basis Technology Corp. + * Contact: carrier sleuthkit org + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.sleuthkit.autopsy.imagegallery; + +import com.google.common.collect.Sets; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import static java.util.Objects.isNull; +import static java.util.Objects.nonNull; +import java.util.Optional; +import java.util.Set; +import java.util.logging.Level; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.imageio.ImageIO; +import org.sleuthkit.autopsy.coreutils.ImageUtils; +import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.modules.filetypeid.FileTypeDetector; +import org.sleuthkit.datamodel.AbstractFile; +import org.sleuthkit.datamodel.TskCoreException; + +/** + * + */ +public enum FileTypeUtils { + + instance; + + private static final Set supportedMimeTypes = new HashSet<>(); + + public static Set getAllSupportedMimeTypes() { + return Collections.unmodifiableSet(supportedMimeTypes); + } + private static final Set imageExtensions = new HashSet<>(); + static final Set videoExtensions = new HashSet<>(); + static final Set supportedExtensions; + + static { + imageExtensions.addAll(Stream.of(ImageIO.getReaderFileSuffixes()) + .map(String::toLowerCase) + .collect(Collectors.toList())); + imageExtensions.addAll(Arrays.asList("bmp", "gif", "jpg", "jpeg", + "png", "tga", "psd", "tif", "tiff", "yuv", "ico", "ai", "svg")); + + videoExtensions.addAll(Arrays.asList("fxm", "aaf", "3gp", "asf", "avi", "m1v", "m2v", "m4v", + "mp4", "mov", "mpeg", "mpg", "mpe", "mp4", "rm", "wmv", + "mpv", "flv", "swf")); + + supportedExtensions = Sets.union(imageExtensions, videoExtensions); + + supportedMimeTypes.addAll(Stream.of(ImageIO.getReaderMIMETypes()) + .map(String::toLowerCase) + .collect(Collectors.toList())); + + supportedMimeTypes.addAll(Arrays.asList("application/x-shockwave-flash")); + } + + private static FileTypeDetector FILE_TYPE_DETECTOR; + + private static final Logger LOGGER = Logger.getLogger(FileTypeUtils.class.getName()); + + static Set getAllSupportedExtensions() { + return Collections.unmodifiableSet(supportedExtensions); + } + + static synchronized FileTypeDetector getFileTypeDetector() { + if (isNull(FILE_TYPE_DETECTOR)) { + try { + FILE_TYPE_DETECTOR = new FileTypeDetector(); + } catch (FileTypeDetector.FileTypeDetectorInitException ex) { + LOGGER.log(Level.SEVERE, "Failed to initialize File Type Detector, will fall back on extensions in some situations.", ex); + } + } + return FILE_TYPE_DETECTOR; + } + + /** is the given file supported by image analyzer? ie, does it have a + * supported mime type (image/*, or video/*). if no mime type is found, does + * it have a supported extension or a jpeg/png header? + * + * @param file + * + * @return true if this file is supported or false if not + */ + public static Boolean isDrawable(AbstractFile file) { + return hasDrawableMimeType(file).orElseGet(() -> { + return FileTypeUtils.supportedExtensions.contains(file.getNameExtension()) + || ImageUtils.isJpegFileHeader(file) + || ImageUtils.isPngFileHeader(file); + }); + } + + /** + * + * + * @param file + * + * @return an Optional containg: + * True if the file has an image or video mime type. + * False if a non image/video mimetype. + * null empty Optional if a mimetype could not be detected. + */ + static Optional hasDrawableMimeType(AbstractFile file) { + try { + final FileTypeDetector fileTypeDetector = getFileTypeDetector(); + if (nonNull(fileTypeDetector)) { + String mimeType = fileTypeDetector.getFileType(file); + if (isNull(mimeType)) { + return Optional.empty(); + } else { + mimeType = mimeType.toLowerCase(); + return Optional.of(mimeType.startsWith("image/") + || mimeType.startsWith("video/") + || supportedMimeTypes.contains(mimeType)); + } + } + } catch (TskCoreException ex) { + LOGGER.log(Level.INFO, "failed to get mime type for " + file.getName(), ex); + } + return Optional.empty(); + } + + /** @param file + * + * @return true if the given file has a video mime type (video/*, + * application/x-shockwave-flash, etc) or, if no mimetype is + * available, a video extension. + */ + public static boolean isVideoFile(AbstractFile file) { + try { + final FileTypeDetector fileTypeDetector = getFileTypeDetector(); + if (nonNull(fileTypeDetector)) { + String mimeType = fileTypeDetector.getFileType(file); + if (nonNull(mimeType)) { + mimeType = mimeType.toLowerCase(); + return mimeType.startsWith("video/") || supportedMimeTypes.contains(mimeType); + } + } + } catch (TskCoreException ex) { + LOGGER.log(Level.INFO, "failed to get mime type for " + file.getName(), ex); + } + return FileTypeUtils.videoExtensions.contains(file.getNameExtension()); + } +} diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java index ae4e1dd21d..5b8b59c05b 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryController.java @@ -22,6 +22,7 @@ import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.Optional; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import java.util.logging.Level; @@ -204,7 +205,7 @@ public final class ImageGalleryController { //if we just turned on listening and a case is open and that case is not up to date if (newValue && !oldValue && Case.existsCurrentCase() && ImageGalleryModule.isDrawableDBStale(Case.getCurrentCase())) { //populate the db - queueDBWorkerTask(new CopyAnalyzedFiles()); + queueDBWorkerTask(new CopyAnalyzedFiles(instance, db, sleuthKitCase)); } }); @@ -456,11 +457,11 @@ public final class ImageGalleryController { if (isListeningEnabled()) { if (ImageGalleryModule.isDrawableAndNotKnown(file)) { //this file should be included and we don't already know about it from hash sets (NSRL) - queueDBWorkerTask(new UpdateFileTask(file)); - } else if (ImageGalleryModule.getAllSupportedExtensions().contains(file.getNameExtension())) { + queueDBWorkerTask(new UpdateFileTask(file, db)); + } else if (FileTypeUtils.getAllSupportedExtensions().contains(file.getNameExtension())) { //doing this check results in fewer tasks queued up, and faster completion of db update //this file would have gotten scooped up in initial grab, but actually we don't need it - queueDBWorkerTask(new RemoveFileTask(file)); + queueDBWorkerTask(new RemoveFileTask(file, db)); } } else { //TODO: keep track of what we missed for later setStale(true); @@ -501,7 +502,7 @@ public final class ImageGalleryController { getTagsManager().fireTagDeletedEvent(tagDeletedEvent); } break; - + } }); } @@ -518,8 +519,6 @@ public final class ImageGalleryController { return tagsManager; } - - // @@@ REVIEW IF THIS SHOLD BE STATIC... //TODO: concept seems like the controller deal with how much work to do at a given time // @@@ review this class for synchronization issues (i.e. reset and cancel being called, add, etc.) @@ -651,14 +650,20 @@ public final class ImageGalleryController { static public abstract class FileTask extends InnerTask { private final AbstractFile file; + private final DrawableDB taskDB; + + public DrawableDB getTaskDB() { + return taskDB; + } public AbstractFile getFile() { return file; } - public FileTask(AbstractFile f) { + public FileTask(AbstractFile f, DrawableDB taskDB) { super(); this.file = f; + this.taskDB = taskDB; } } @@ -666,10 +671,10 @@ public final class ImageGalleryController { /** * task that updates one file in database with results from ingest */ - private class UpdateFileTask extends FileTask { + static private class UpdateFileTask extends FileTask { - public UpdateFileTask(AbstractFile f) { - super(f); + public UpdateFileTask(AbstractFile f, DrawableDB taskDB) { + super(f, taskDB); } /** @@ -678,8 +683,8 @@ public final class ImageGalleryController { @Override public void run() { try { - DrawableFile drawableFile = DrawableFile.create(getFile(), true, db.isVideoFile(getFile())); - db.updateFile(drawableFile); + DrawableFile drawableFile = DrawableFile.create(getFile(), true, getTaskDB().isVideoFile(getFile())); + getTaskDB().updateFile(drawableFile); } catch (NullPointerException ex) { // This is one of the places where we get many errors if the case is closed during processing. // We don't want to print out a ton of exceptions if this is the case. @@ -693,10 +698,10 @@ public final class ImageGalleryController { /** * task that updates one file in database with results from ingest */ - private class RemoveFileTask extends FileTask { + static private class RemoveFileTask extends FileTask { - public RemoveFileTask(AbstractFile f) { - super(f); + public RemoveFileTask(AbstractFile f, DrawableDB taskDB) { + super(f, taskDB); } /** @@ -705,7 +710,7 @@ public final class ImageGalleryController { @Override public void run() { try { - db.removeFile(getFile().getId()); + getTaskDB().removeFile(getFile().getId()); } catch (NullPointerException ex) { // This is one of the places where we get many errors if the case is closed during processing. // We don't want to print out a ton of exceptions if this is the case. @@ -720,13 +725,42 @@ public final class ImageGalleryController { /** * Task that runs when image gallery listening is (re) enabled. * - * Uses the presence of TSK_FILE_TYPE_SIG attributes as a approximation to - * 'analyzed'. Grabs all files with supported image/video mime types, and - * adds them to the Drawable DB + * Grabs all files with supported image/video mime types or extensions, and + * adds them to the Drawable DB. Uses the presence of TSK_FILE_TYPE_SIG + * attributes as a approximation to 'analyzed'. + * */ - private class CopyAnalyzedFiles extends InnerTask { + static private class CopyAnalyzedFiles extends InnerTask { - final private String DRAWABLE_QUERY = "name LIKE '%." + StringUtils.join(ImageGalleryModule.getAllSupportedExtensions(), "' or name LIKE '%.") + "'"; + private final ImageGalleryController controller; + private final DrawableDB taskDB; + private final SleuthkitCase tskCase; + + public CopyAnalyzedFiles(ImageGalleryController controller, DrawableDB taskDB, SleuthkitCase tskCase) { + this.controller = controller; + this.taskDB = taskDB; + this.tskCase = tskCase; + } + + static private final String FILE_EXTESNION_CLAUSE = "(name LIKE '%." + + StringUtils.join(FileTypeUtils.getAllSupportedExtensions(), + "' or name LIKE '%.") + + "')"; + static private final String MIMETYPE_CLAUSE + = "blackboard_attributes.value_text LIKE " + + StringUtils.join(FileTypeUtils.getAllSupportedMimeTypes(), + " OR blackboard_attributes.value_text LIKE "); + + static private final String DRAWABLE_QUERY = FILE_EXTESNION_CLAUSE + " OR tsk_files.obj_id IN (" + + "SELECT tsk_files.obj_id from tsk_files , blackboard_artifacts, blackboard_attributes" + + " WHERE blackboard_artifacts.obj_id = tsk_files.obj_id" + + " AND blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id" + + " AND blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID() + + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG.getTypeID() + + " AND (blackboard_attributes.value_text LIKE 'video/%'" + + " OR blackboard_attributes.value_text LIKE 'image/%'" + + " OR " + MIMETYPE_CLAUSE + + " )"; private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("populating analyzed image/video database"); @@ -737,21 +771,13 @@ public final class ImageGalleryController { try { //grab all files with supported extension or detected mime types - final List files = getSleuthKitCase().findAllFilesWhere(DRAWABLE_QUERY + " OR tsk_files.obj_id IN (" - + "SELECT tsk_files.obj_id from tsk_files , blackboard_artifacts, blackboard_attributes" - + " WHERE blackboard_artifacts.obj_id = tsk_files.obj_id" - + " AND blackboard_attributes.artifact_id = blackboard_artifacts.artifact_id" - + " AND blackboard_artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_GEN_INFO.getTypeID() - + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_FILE_TYPE_SIG.getTypeID() - + " AND (blackboard_attributes.value_text LIKE 'video/%'" - + " OR blackboard_attributes.value_text LIKE 'image/%'" - + " OR blackboard_attributes.value_text LIKE 'application/x-shockwave-flash'))"); + final List files = tskCase.findAllFilesWhere(DRAWABLE_QUERY); progressHandle.switchToDeterminate(files.size()); updateProgress(0.0); //do in transaction - DrawableDB.DrawableTransaction tr = db.beginTransaction(); + DrawableDB.DrawableTransaction tr = taskDB.beginTransaction(); int units = 0; for (final AbstractFile f : files) { if (cancelled) { @@ -763,22 +789,22 @@ public final class ImageGalleryController { final boolean known = f.getKnown() == TskData.FileKnown.KNOWN; if (known) { - db.removeFile(f.getId(), tr); //remove known files + taskDB.removeFile(f.getId(), tr); //remove known files } else { - final Boolean hasMimeType = ImageGalleryModule.hasDrawableMimeType(f); - if (hasMimeType == null) { - if (ImageGalleryModule.isDrawable(f)) { - //no mime type but supported => add as not analyzed - db.insertFile(DrawableFile.create(f, false, db.isVideoFile(f)), tr); - } else { - //no mime type, not supported => remove ( should never get here) - db.removeFile(f.getId(), tr); + final Optional hasMimeType = FileTypeUtils.hasDrawableMimeType(f); + if (hasMimeType.isPresent()) { + if (hasMimeType.get()) { // supported mimetype => analyzed + taskDB.updateFile(DrawableFile.create(f, true, taskDB.isVideoFile(f)), tr); + } else { //unsupported mimtype => analyzed but shouldn't include + taskDB.removeFile(f.getId(), tr); } } else { - if (hasMimeType) { // supported mimetype => analyzed - db.updateFile(DrawableFile.create(f, true, db.isVideoFile(f)), tr); - } else { //unsupported mimtype => analyzed but shouldn't include - db.removeFile(f.getId(), tr); + if (FileTypeUtils.isDrawable(f)) { + //no mime type but supported => add as not analyzed + taskDB.insertFile(DrawableFile.create(f, false, taskDB.isVideoFile(f)), tr); + } else { + //no mime type, not supported => remove ( should never get here) + taskDB.removeFile(f.getId(), tr); } } } @@ -797,7 +823,7 @@ public final class ImageGalleryController { updateProgress(1.0); progressHandle.start(); - db.commitTransaction(tr, true); + taskDB.commitTransaction(tr, true); } catch (TskCoreException ex) { Logger.getLogger(CopyAnalyzedFiles.class.getName()).log(Level.WARNING, "failed to transfer all database contents", ex); @@ -809,9 +835,8 @@ public final class ImageGalleryController { updateMessage(""); updateProgress(-1.0); - setStale(false); + controller.setStale(false); } - } /** @@ -831,7 +856,7 @@ public final class ImageGalleryController { * check for supported images */ // (name like '.jpg' or name like '.png' ...) - private final String DRAWABLE_QUERY = "(name LIKE '%." + StringUtils.join(ImageGalleryModule.getAllSupportedExtensions(), "' or name LIKE '%.") + "') "; + private final String DRAWABLE_QUERY = "(name LIKE '%." + StringUtils.join(FileTypeUtils.getAllSupportedExtensions(), "' or name LIKE '%.") + "') "; private ProgressHandle progressHandle = ProgressHandleFactory.createHandle("prepopulating image/video database"); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java index 4b73dc7ee4..176086d960 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/ImageGalleryModule.java @@ -50,27 +50,6 @@ public class ImageGalleryModule { return MODULE_NAME; } - private static final Set videoExtensions - = Sets.newHashSet("aaf", "3gp", "asf", "avi", "m1v", "m2v", "m4v", "mp4", - "mov", "mpeg", "mpg", "mpe", "mp4", "rm", "wmv", "mpv", - "flv", "swf"); - - private static final Set imageExtensions = Sets.newHashSet(ImageIO.getReaderFileSuffixes()); - - private static final Set supportedExtensions = Sets.union(imageExtensions, videoExtensions); - - private static FileTypeDetector FILE_TYPE_DETECTOR; - - private static synchronized FileTypeDetector getFileTypeDetector() { - if (isNull(FILE_TYPE_DETECTOR)) { - try { - FILE_TYPE_DETECTOR = new FileTypeDetector(); - } catch (FileTypeDetector.FileTypeDetectorInitException ex) { - LOGGER.log(Level.SEVERE, "Failed to initialize File Type Detector, will fall back on extensions in some situations.", ex); - } - } - return FILE_TYPE_DETECTOR; - } /** * get the Path to the Case's ImageGallery ModuleOutput subfolder; ie @@ -120,69 +99,9 @@ public class ImageGalleryModule { } } - static Set getAllSupportedExtensions() { - return Collections.unmodifiableSet(supportedExtensions); - } - /** is the given file suported by image analyzer: ie, does it have a - * supported mime type (image/*, or video/*). if no mime type is found, does - * it have a supported extension or a jpeg/png header. - * - * @param file - * - * @return true if this file is supported or false if not - */ - static Boolean isDrawable(AbstractFile file) { - //if there were no file type attributes, fall back on extension and jpeg header - return Optional.ofNullable(hasDrawableMimeType(file)).orElseGet(() -> { - return supportedExtensions.contains(file.getNameExtension()) - || ImageUtils.isJpegFileHeader(file) || ImageUtils.isPngFileHeader(file); - }); - } - /** - * - * @param file - * - * @return true if the file has an image or video mime type. - * false if a non image/video mimetype. - * null if a mimetype could not be detected. - */ - static Boolean hasDrawableMimeType(AbstractFile file) { - try { - final FileTypeDetector fileTypeDetector = getFileTypeDetector(); - if (nonNull(fileTypeDetector)) { - String mimeType = fileTypeDetector.getFileType(file); - return isNull(mimeType) ? null - : mimeType.startsWith("image/") || mimeType.startsWith("video/") || mimeType.equalsIgnoreCase("application/x-shockwave-flash"); - } - } catch (TskCoreException ex) { - LOGGER.log(Level.INFO, "failed to get mime type for " + file.getName(), ex); - } - return null; - } - /** @param file - * - * @return true if the given file has a video mime type (video/* or - * application/x-shockwave-flash) or if no mimetype is available a video - * extension - */ - public static boolean isVideoFile(AbstractFile file) { - try { - final FileTypeDetector fileTypeDetector = getFileTypeDetector(); - if (nonNull(fileTypeDetector)) { - String mimeType = fileTypeDetector.getFileType(file); - if (nonNull(mimeType)) { - return mimeType.startsWith("video/") || mimeType.equalsIgnoreCase("application/x-shockwave-flash"); - } - } - } catch (TskCoreException ex) { - LOGGER.log(Level.INFO, "failed to get mime type for " + file.getName(), ex); - - } - return videoExtensions.contains(file.getNameExtension()); - } /** * Is the given file 'supported' and not 'known'(nsrl hash hit). If so we @@ -194,6 +113,6 @@ public class ImageGalleryModule { * 'known', else false */ public static boolean isDrawableAndNotKnown(AbstractFile abstractFile) { - return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && ImageGalleryModule.isDrawable(abstractFile); + return (abstractFile.getKnown() != TskData.FileKnown.KNOWN) && FileTypeUtils.isDrawable(abstractFile); } } diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java index c330fa6865..7047d5291a 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableDB.java @@ -46,8 +46,8 @@ import org.apache.commons.lang3.StringUtils; import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.imagegallery.FileTypeUtils; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupKey; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupManager; import org.sleuthkit.autopsy.imagegallery.datamodel.grouping.GroupSortBy; @@ -1199,7 +1199,7 @@ public final class DrawableDB { private final Map videoFileMap = new ConcurrentHashMap<>(); public boolean isVideoFile(AbstractFile f) { - return videoFileMap.computeIfAbsent(f, ImageGalleryModule::isVideoFile); + return videoFileMap.computeIfAbsent(f, FileTypeUtils::isVideoFile); } /** diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java index 34806aceac..61024125ee 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/DrawableFile.java @@ -35,6 +35,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.Logger; +import org.sleuthkit.autopsy.imagegallery.FileTypeUtils; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule; import org.sleuthkit.datamodel.AbstractFile; @@ -62,7 +63,7 @@ import org.sleuthkit.datamodel.TskCoreException; public abstract class DrawableFile extends AbstractFile { public static DrawableFile create(AbstractFile abstractFileById, boolean analyzed) { - if (ImageGalleryModule.isVideoFile(abstractFileById)) { + if (FileTypeUtils.isVideoFile(abstractFileById)) { return new VideoFile<>(abstractFileById, analyzed); } else { return new ImageFile<>(abstractFileById, analyzed); @@ -83,7 +84,7 @@ public abstract class DrawableFile extends AbstractFile public static DrawableFile create(Long id, boolean analyzed) throws TskCoreException, IllegalStateException { AbstractFile abstractFileById = Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(id); - if (ImageGalleryModule.isVideoFile(abstractFileById)) { + if (FileTypeUtils.isVideoFile(abstractFileById)) { return new VideoFile<>(abstractFileById, analyzed); } else { return new ImageFile<>(abstractFileById, analyzed); diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java index 720ddab845..738ee8a765 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/VideoFile.java @@ -27,19 +27,24 @@ import javafx.scene.media.Media; import javafx.scene.media.MediaException; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.datamodel.ContentUtils; -import org.sleuthkit.autopsy.imagegallery.FileTypeIcons; import org.sleuthkit.datamodel.AbstractFile; public class VideoFile extends DrawableFile { + private static final Image VIDEO_ICON = new Image("org/sleuthkit/autopsy/imagegallery/images/Clapperboard.png"); + VideoFile(T file, Boolean analyzed) { super(file, analyzed); } + public static Image getGenericVideoThumbnail() { + return VIDEO_ICON; + } + @Override public Image getThumbnail() { //TODO: implement video thumbnailing here? - return FileTypeIcons.getGenericVideoThumbnail(); + return getGenericVideoThumbnail(); } SoftReference mediaRef; diff --git a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java index 73fccb4d29..e1c7f802c3 100644 --- a/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java +++ b/ImageGallery/src/org/sleuthkit/autopsy/imagegallery/datamodel/grouping/GroupManager.java @@ -19,8 +19,6 @@ package org.sleuthkit.autopsy.imagegallery.datamodel.grouping; import com.google.common.eventbus.Subscribe; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -58,7 +56,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.concurrent.BasicThreadFactory; import org.netbeans.api.progress.ProgressHandle; import org.netbeans.api.progress.ProgressHandleFactory; -import org.openide.util.Exceptions; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.LoggedTask; import org.sleuthkit.autopsy.coreutils.ThreadConfined; @@ -66,7 +63,6 @@ import org.sleuthkit.autopsy.coreutils.ThreadConfined.ThreadType; import org.sleuthkit.autopsy.events.ContentTagAddedEvent; import org.sleuthkit.autopsy.events.ContentTagDeletedEvent; import org.sleuthkit.autopsy.imagegallery.ImageGalleryController; -import org.sleuthkit.autopsy.imagegallery.ImageGalleryModule; import org.sleuthkit.autopsy.imagegallery.datamodel.Category; import org.sleuthkit.autopsy.imagegallery.datamodel.CategoryManager; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableAttribute; @@ -74,8 +70,6 @@ import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableDB; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableFile; import org.sleuthkit.autopsy.imagegallery.datamodel.DrawableTagsManager; import org.sleuthkit.datamodel.AbstractFile; -import org.sleuthkit.datamodel.BlackboardArtifact; -import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.ContentTag; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TagName; @@ -302,59 +296,6 @@ public class GroupManager { return group; } - /** - * the implementation of this should be moved to DrawableDB - * - * @param hashDbName - * - * @return - * - * @deprecated - */ - @Deprecated - private List getFileIDsWithHashSetName(String hashDbName) { - List files = new ArrayList<>(); - try { - - final SleuthkitCase sleuthkitCase = ImageGalleryController.getDefault().getSleuthKitCase(); - String query = "SELECT obj_id FROM blackboard_attributes,blackboard_artifacts WHERE " - + "attribute_type_id=" + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_SET_NAME.getTypeID() - + " AND blackboard_attributes.artifact_id=blackboard_artifacts.artifact_id" - + " AND blackboard_attributes.value_text='" + hashDbName + "'" - + " AND blackboard_artifacts.artifact_type_id=" + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID(); - - ResultSet rs = null; - try { - rs = sleuthkitCase.runQuery(query); - while (rs.next()) { - long id = rs.getLong("obj_id"); - try { - if (ImageGalleryModule.isDrawableAndNotKnown(Case.getCurrentCase().getSleuthkitCase().getAbstractFileById(id))) { - files.add(id); - } - } catch (TskCoreException ex) { - Exceptions.printStackTrace(ex); - } - } - } catch (SQLException ex) { - Exceptions.printStackTrace(ex); - } finally { - if (rs != null) { - try { - Case.getCurrentCase().getSleuthkitCase().closeRunQuery(rs); - } catch (SQLException ex) { - LOGGER.log(Level.WARNING, "Error closing result set after getting hashset hits", ex); - } - } - } - - return files; - } catch (IllegalStateException ex) { - LOGGER.log(Level.SEVERE, "Can't get the current case; there is no case open!", ex); - return files; - } - } - /** * find the distinct values for the given column (DrawableAttribute) *