19package org.sleuthkit.autopsy.datamodel;
21import java.io.FileOutputStream;
22import java.io.IOException;
23import java.io.InputStream;
24import java.text.SimpleDateFormat;
25import java.util.TimeZone;
26import java.util.concurrent.Future;
27import java.util.function.Supplier;
28import java.util.logging.Level;
29import javax.swing.SwingWorker;
30import org.netbeans.api.progress.ProgressHandle;
31import org.openide.util.NbBundle;
32import org.sleuthkit.autopsy.core.UserPreferences;
33import org.sleuthkit.autopsy.coreutils.Logger;
34import org.sleuthkit.datamodel.AbstractFile;
35import org.sleuthkit.datamodel.Content;
36import org.sleuthkit.datamodel.ContentVisitor;
37import org.sleuthkit.datamodel.DerivedFile;
38import org.sleuthkit.datamodel.Directory;
39import org.sleuthkit.datamodel.File;
40import org.sleuthkit.datamodel.LayoutFile;
41import org.sleuthkit.datamodel.LocalFile;
42import org.sleuthkit.datamodel.LocalDirectory;
43import org.sleuthkit.datamodel.ReadContentInputStream;
44import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
45import org.sleuthkit.datamodel.SlackFile;
46import org.sleuthkit.datamodel.TskCoreException;
47import org.sleuthkit.datamodel.VirtualDirectory;
55 private static final SimpleDateFormat
dateFormatter =
new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss z");
56 private static final SimpleDateFormat
dateFormatterISO8601 =
new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss'Z'");
62 throw new AssertionError();
75 String time =
"0000-00-00 00:00:00";
76 if (epochSeconds != 0) {
79 time =
dateFormatter.format(
new java.util.Date(epochSeconds * 1000));
95 String time =
"0000-00-00T00:00:00Z";
96 if (epochSeconds != 0) {
151 return TimeZone.getDefault();
171 private static class SystemNameVisitor
extends ContentVisitor.Default<String> {
173 SystemNameVisitor() {
178 return cntnt.getName() +
":" + Long.toString(cntnt.getId());
201 public static <T>
long writeToFile(Content content, java.io.File outputFile,
202 ProgressHandle
progress, Future<T> worker,
boolean source)
throws IOException {
203 InputStream in =
new ReadContentInputStream(content);
206 int unit = (int) (content.getSize() / 100);
209 try (FileOutputStream out =
new FileOutputStream(outputFile,
false)) {
211 int len = in.read(buffer);
214 if (worker !=
null && worker.isCancelled()) {
217 out.write(buffer, 0, len);
218 len = in.read(buffer);
223 int totalProgress = (int) (totalRead / unit);
224 progress.progress(content.getName(), totalProgress);
226 }
else if (
progress !=
null && !source) {
227 progress.progress(content.getName());
244 public static void writeToFile(Content content, java.io.File outputFile)
throws IOException {
245 writeToFile(content, outputFile,
null,
null,
false);
262 public static long writeToFile(Content content, java.io.File outputFile,
263 Supplier<Boolean> cancelCheck)
throws IOException {
264 InputStream in =
new ReadContentInputStream(content);
267 try (FileOutputStream out =
new FileOutputStream(outputFile,
false)) {
269 int len = in.read(buffer);
271 out.write(buffer, 0, len);
273 if (cancelCheck.get()) {
276 len = in.read(buffer);
300 public static long writeToFile(Content content, java.io.File outputFile,
301 Supplier<Boolean> cancelCheck,
long startingOffset,
long endingOffset)
throws IOException {
303 InputStream in =
new ReadContentInputStream(content);
305 try (FileOutputStream out =
new FileOutputStream(outputFile,
false)) {
306 long offsetSkipped = in.skip(startingOffset);
307 if (offsetSkipped != startingOffset) {
309 throw new IOException(String.format(
"Skipping file to starting offset {0} was not successful only skipped to offset {1}.", startingOffset, offsetSkipped));
312 int len = in.read(buffer);
313 long writeFileLength = endingOffset - startingOffset;
315 while (len != -1 && writeFileLength != 0) {
316 out.write(buffer, 0, len);
318 if (cancelCheck.get()) {
322 len = in.read(buffer);
325 int writeLength = (int)writeFileLength;
326 byte[] lastBuffer =
new byte[writeLength];
327 len = in.read(lastBuffer);
328 out.write(lastBuffer, 0, len);
348 String name = dir.getName();
349 return name.equals(
".") || name.equals(
"..");
360 ProgressHandle progress;
361 SwingWorker<T, V> worker;
362 boolean source =
false;
377 ProgressHandle progress, SwingWorker<T, V> worker,
boolean source) {
379 this.progress = progress;
380 this.worker = worker;
381 this.source = source;
392 public static <T, V>
void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker<T, V> worker) {
410 protected void writeFile(Content file, java.io.File dest, ProgressHandle progress, SwingWorker<T, V> worker,
boolean source)
throws IOException {
411 ContentUtils.writeToFile(file, dest, progress, worker, source);
420 protected Void
visitFile(Content file, String fileType) {
422 writeFile(file, dest, progress, worker, source);
423 }
catch (ReadContentInputStreamException ex) {
425 String.format(
"Error reading file '%s' (id=%d).",
426 file.getName(), file.getId()), ex);
427 }
catch (IOException ex) {
429 String.format(
"Error extracting %s '%s' (id=%d) to '%s'.",
430 fileType, file.getName(), file.getId(), dest.getAbsolutePath()), ex);
441 public Void
visit(LayoutFile file) {
442 return visitFile(file,
"unallocated content file");
446 public Void
visit(DerivedFile file) {
466 public Void
visit(VirtualDirectory dir) {
471 public Void
visit(LocalDirectory dir) {
476 String path = dest.getAbsolutePath() + java.io.File.separator
478 return new java.io.File(path);
505 int numProcessed = 0;
507 for (Content child : dir.getChildren()) {
508 if (child instanceof AbstractFile) {
514 if (worker !=
null && worker.isCancelled()) {
517 if (progress !=
null && source) {
518 progress.progress(child.getName(), numProcessed);
520 child.accept(childVisitor);
524 }
catch (TskCoreException ex) {
526 "Trouble fetching children to extract.", ex);
534 throw new UnsupportedOperationException(NbBundle.getMessage(
this.getClass(),
535 "ContentUtils.exception.msg",
536 content.getClass().getSimpleName()));
static boolean displayTimesInLocalTime()
static String getTimeZoneForDisplays()
synchronized static Logger getLogger(String name)
String defaultVisit(Content cntnt)
static TimeZone getTimeZone(Content content)
static final SimpleDateFormat dateFormatter
static final SimpleDateFormat dateFormatterISO8601
static void writeToFile(Content content, java.io.File outputFile)
static String getStringTime(long epochSeconds, Content content)
static String getStringTimeISO8601(long epochSeconds, Content c)
static boolean isDotDirectory(AbstractFile dir)
static String getStringTime(long epochSeconds, TimeZone tzone)
static final SystemNameVisitor systemName
static final Logger logger
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
static long writeToFile(Content content, java.io.File outputFile, Supplier< Boolean > cancelCheck)
static String getSystemName(Content content)
static String getStringTimeISO8601(long epochSeconds, TimeZone tzone)
static long writeToFile(Content content, java.io.File outputFile, Supplier< Boolean > cancelCheck, long startingOffset, long endingOffset)
static boolean shouldDisplayTimesInLocalTime()
static final int TO_FILE_BUFFER_SIZE