19 package org.sleuthkit.autopsy.modules.pictureanalyzer.impls;
21 import java.util.HashSet;
23 import java.util.logging.Level;
24 import java.util.Arrays;
25 import java.util.concurrent.TimeUnit;
28 import java.io.IOException;
29 import java.io.InputStream;
31 import java.nio.file.Files;
32 import java.nio.file.Path;
33 import java.nio.file.Paths;
34 import java.nio.file.attribute.BasicFileAttributes;
35 import java.text.MessageFormat;
36 import java.util.List;
37 import org.apache.commons.io.FileUtils;
39 import org.apache.commons.io.FilenameUtils;
41 import org.openide.util.lookup.ServiceProvider;
64 @ServiceProvider(service = PictureProcessor.class)
69 private static final String HEIC_MODULE_FOLDER =
"HEIC";
76 }
catch (UnsatisfiedLinkError ex) {
77 logger.log(Level.SEVERE,
"libheif native dependencies not found. HEIC functionality will be automatically disabled.", ex);
80 this.heifJNI = heifJNI;
86 if (heifJNI == null) {
94 if (file == null || file.getId() <= 0) {
99 try (InputStream is =
new ReadContentInputStream(file)) {
100 heifBytes =
new byte[is.available()];
104 if (heifBytes == null || heifBytes.length == 0) {
108 convertToJPEG(context, heifBytes, file);
109 }
catch (IOException ex) {
110 logger.log(Level.WARNING,
"I/O error encountered during HEIC photo processing.", ex);
111 }
catch (TskCoreException ex) {
112 logger.log(Level.SEVERE,
"Unable to add pictures as derived files.", ex);
114 logger.log(Level.WARNING,
"No open case!", ex);
128 Path moduleOutputFolder = Paths.get(moduleOutputDirectory,
130 String.valueOf(file.getId()));
132 if (!Files.exists(moduleOutputFolder)) {
133 Files.createDirectories(moduleOutputFolder);
136 return moduleOutputFolder;
142 Path outputFolder = createModuleOutputFolder(heicFile);
145 final Path outputFile = outputFolder.resolve(baseFileName +
".jpg");
147 if (context.fileIngestIsCancelled()) {
152 this.heifJNI.
convertToDisk(heifBytes, outputFile.toString());
153 }
catch (IllegalArgumentException | IllegalStateException ex) {
154 logger.log(Level.WARNING, MessageFormat.format(
"There was an error processing {0} (id: {1}).", heicFile.getName(), heicFile.getId()), ex);
156 }
catch (Throwable ex) {
157 logger.log(Level.SEVERE, MessageFormat.format(
"A severe error occurred while processing {0} (id: {1}).", heicFile.getName(), heicFile.getId()), ex);
161 if (context.fileIngestIsCancelled()) {
167 List<File> files = (List<File>) FileUtils.listFiles(outputFolder.toFile(),
new String[]{
"jpg",
"jpeg"},
true);
168 for (File file : files) {
169 if (context.fileIngestIsCancelled()) {
173 Path candidate = file.toPath();
175 final BasicFileAttributes attrs = Files.readAttributes(candidate, BasicFileAttributes.class);
176 final Path localCasePath = caseDirectory.relativize(candidate);
179 .addDerivedFile(candidate.getFileName().toString(),
180 localCasePath.toString(), attrs.size(), 0L,
181 attrs.creationTime().to(TimeUnit.SECONDS),
182 attrs.lastAccessTime().to(TimeUnit.SECONDS),
183 attrs.lastModifiedTime().to(TimeUnit.SECONDS),
184 attrs.isRegularFile(), heicFile,
"",
185 "",
"",
"", TskData.EncodingType.NONE);
187 context.addFilesToJob(Arrays.asList(jpegFile));
194 return new HashSet<String>() {
static HeifJNI getInstance()
String getCaseDirectory()
Set< String > mimeTypes()
SleuthkitCase getSleuthkitCase()
String getModuleDirectory()
boolean fileIngestIsCancelled()
void convertToJPEG(IngestJobContext context, byte[] heifBytes, AbstractFile heicFile)
void fireModuleContentEvent(ModuleContentEvent moduleContentEvent)
Path createModuleOutputFolder(AbstractFile file)
native int convertToDisk(byte[] data, String jpgOutputPath)
static String escapeFileName(String fileName)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
void process(IngestJobContext context, AbstractFile file)
static synchronized IngestServices getInstance()