mirror of
https://github.com/elisspace/autopsy.git
synced 2026-10-05 08:46:20 +00:00
Extract FileTypeUtils from ImageGalleryModule
remove FileTypeIcons remove deprecated method from GroupManager
This commit is contained in:
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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<String, Image> 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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Autopsy Forensic Browser
|
||||
*
|
||||
* Copyright 2015 Basis Technology Corp.
|
||||
* Contact: carrier <at> sleuthkit <dot> 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<String> supportedMimeTypes = new HashSet<>();
|
||||
|
||||
public static Set<String> getAllSupportedMimeTypes() {
|
||||
return Collections.unmodifiableSet(supportedMimeTypes);
|
||||
}
|
||||
private static final Set<String> imageExtensions = new HashSet<>();
|
||||
static final Set<String> videoExtensions = new HashSet<>();
|
||||
static final Set<String> 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<String> 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<Boolean> 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());
|
||||
}
|
||||
}
|
||||
@@ -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<AbstractFile> 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<AbstractFile> 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<Boolean> 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");
|
||||
|
||||
|
||||
@@ -50,27 +50,6 @@ public class ImageGalleryModule {
|
||||
return MODULE_NAME;
|
||||
}
|
||||
|
||||
private static final Set<String> 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<String> imageExtensions = Sets.newHashSet(ImageIO.getReaderFileSuffixes());
|
||||
|
||||
private static final Set<String> 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<String> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<AbstractFile, Boolean> videoFileMap = new ConcurrentHashMap<>();
|
||||
|
||||
public boolean isVideoFile(AbstractFile f) {
|
||||
return videoFileMap.computeIfAbsent(f, ImageGalleryModule::isVideoFile);
|
||||
return videoFileMap.computeIfAbsent(f, FileTypeUtils::isVideoFile);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<T extends AbstractFile> 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<T extends AbstractFile> 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);
|
||||
|
||||
@@ -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<T extends AbstractFile> extends DrawableFile<T> {
|
||||
|
||||
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<Media> mediaRef;
|
||||
|
||||
-59
@@ -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<Long> getFileIDsWithHashSetName(String hashDbName) {
|
||||
List<Long> 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)
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user