Autopsy  4.19.1
Graphical digital forensics platform for The Sleuth Kit and other tools.
ContentUtils.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2011-2018 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.datamodel;
20 
21 import java.io.FileOutputStream;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.text.SimpleDateFormat;
25 import java.util.TimeZone;
26 import java.util.concurrent.Future;
27 import java.util.function.Supplier;
28 import java.util.logging.Level;
29 import javax.swing.SwingWorker;
30 import org.netbeans.api.progress.ProgressHandle;
31 import org.openide.util.NbBundle;
34 import org.sleuthkit.datamodel.AbstractFile;
35 import org.sleuthkit.datamodel.Content;
36 import org.sleuthkit.datamodel.ContentVisitor;
37 import org.sleuthkit.datamodel.DerivedFile;
38 import org.sleuthkit.datamodel.Directory;
39 import org.sleuthkit.datamodel.File;
40 import org.sleuthkit.datamodel.LayoutFile;
41 import org.sleuthkit.datamodel.LocalFile;
42 import org.sleuthkit.datamodel.LocalDirectory;
43 import org.sleuthkit.datamodel.ReadContentInputStream;
44 import org.sleuthkit.datamodel.ReadContentInputStream.ReadContentInputStreamException;
45 import org.sleuthkit.datamodel.SlackFile;
46 import org.sleuthkit.datamodel.TskCoreException;
47 import org.sleuthkit.datamodel.VirtualDirectory;
48 
52 public final class ContentUtils {
53 
54  private final static Logger logger = Logger.getLogger(ContentUtils.class.getName());
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'");
57 
61  private ContentUtils() {
62  throw new AssertionError();
63  }
64 
73  @Deprecated
74  public static String getStringTime(long epochSeconds, TimeZone tzone) {
75  String time = "0000-00-00 00:00:00";
76  if (epochSeconds != 0) {
77  synchronized (dateFormatter) {
78  dateFormatter.setTimeZone(tzone);
79  time = dateFormatter.format(new java.util.Date(epochSeconds * 1000));
80  }
81  }
82  return time;
83  }
84 
93  @Deprecated
94  public static String getStringTimeISO8601(long epochSeconds, TimeZone tzone) {
95  String time = "0000-00-00T00:00:00Z"; //NON-NLS
96  if (epochSeconds != 0) {
97  synchronized (dateFormatterISO8601) {
98  dateFormatterISO8601.setTimeZone(tzone);
99  time = dateFormatterISO8601.format(new java.util.Date(epochSeconds * 1000));
100  }
101  }
102 
103  return time;
104  }
105 
116  @Deprecated
117  public static String getStringTime(long epochSeconds, Content content) {
118  return getStringTime(epochSeconds, getTimeZone(content));
119  }
120 
132  @Deprecated
133  public static String getStringTimeISO8601(long epochSeconds, Content c) {
134  return getStringTimeISO8601(epochSeconds, getTimeZone(c));
135  }
136 
146  @Deprecated
147  public static TimeZone getTimeZone(Content content) {
149  return TimeZone.getTimeZone(UserPreferences.getTimeZoneForDisplays());
150  } else {
151  return TimeZone.getDefault();
152  }
153  }
154  private static final SystemNameVisitor systemName = new SystemNameVisitor();
155 
163  public static String getSystemName(Content content) {
164  return content.accept(systemName);
165  }
166 
171  private static class SystemNameVisitor extends ContentVisitor.Default<String> {
172 
174  }
175 
176  @Override
177  protected String defaultVisit(Content cntnt) {
178  return cntnt.getName() + ":" + Long.toString(cntnt.getId());
179  }
180  }
181  private static final int TO_FILE_BUFFER_SIZE = 8192;
182 
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);
204 
205  // Get the unit size for a progress bar
206  int unit = (int) (content.getSize() / 100);
207  long totalRead = 0;
208 
209  try (FileOutputStream out = new FileOutputStream(outputFile, false)) {
210  byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
211  int len = in.read(buffer);
212  while (len != -1) {
213  // If there is a worker, check for a cancelation
214  if (worker != null && worker.isCancelled()) {
215  break;
216  }
217  out.write(buffer, 0, len);
218  len = in.read(buffer);
219  totalRead += len;
220  // If there is a progress bar and this is the source file,
221  // report any progress
222  if (progress != null && source && totalRead >= TO_FILE_BUFFER_SIZE) {
223  int totalProgress = (int) (totalRead / unit);
224  progress.progress(content.getName(), totalProgress);
225  // If it's not the source, just update the file being processed
226  } else if (progress != null && !source) {
227  progress.progress(content.getName());
228  }
229  }
230  } finally {
231  in.close();
232  }
233  return totalRead;
234  }
235 
244  public static void writeToFile(Content content, java.io.File outputFile) throws IOException {
245  writeToFile(content, outputFile, null, null, false);
246  }
247 
262  public static long writeToFile(Content content, java.io.File outputFile,
263  Supplier<Boolean> cancelCheck) throws IOException {
264  InputStream in = new ReadContentInputStream(content);
265  long totalRead = 0;
266 
267  try (FileOutputStream out = new FileOutputStream(outputFile, false)) {
268  byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
269  int len = in.read(buffer);
270  while (len != -1) {
271  out.write(buffer, 0, len);
272  totalRead += len;
273  if (cancelCheck.get()) {
274  break;
275  }
276  len = in.read(buffer);
277  }
278  } finally {
279  in.close();
280  }
281  return totalRead;
282  }
283 
300  public static long writeToFile(Content content, java.io.File outputFile,
301  Supplier<Boolean> cancelCheck, long startingOffset, long endingOffset) throws IOException {
302 
303  InputStream in = new ReadContentInputStream(content);
304  long totalRead = 0;
305  try (FileOutputStream out = new FileOutputStream(outputFile, false)) {
306  long offsetSkipped = in.skip(startingOffset);
307  if (offsetSkipped != startingOffset) {
308  in.close();
309  throw new IOException(String.format("Skipping file to starting offset {0} was not successful only skipped to offset {1}.", startingOffset, offsetSkipped));
310  }
311  byte[] buffer = new byte[TO_FILE_BUFFER_SIZE];
312  int len = in.read(buffer);
313  long writeFileLength = endingOffset - startingOffset;
314  writeFileLength = writeFileLength - TO_FILE_BUFFER_SIZE;
315  while (len != -1 && writeFileLength != 0) {
316  out.write(buffer, 0, len);
317  totalRead += len;
318  if (cancelCheck.get()) {
319  break;
320  }
321  if (writeFileLength > TO_FILE_BUFFER_SIZE) {
322  len = in.read(buffer);
323  writeFileLength = writeFileLength - TO_FILE_BUFFER_SIZE;
324  } else {
325  int writeLength = (int)writeFileLength;
326  byte[] lastBuffer = new byte[writeLength];
327  len = in.read(lastBuffer);
328  out.write(lastBuffer, 0, len);
329  totalRead += len;
330  writeFileLength = 0;
331  }
332  }
333 
334  } finally {
335  in.close();
336  }
337  return totalRead;
338  }
339 
347  public static boolean isDotDirectory(AbstractFile dir) {
348  String name = dir.getName();
349  return name.equals(".") || name.equals("..");
350  }
351 
357  public static class ExtractFscContentVisitor<T, V> extends ContentVisitor.Default<Void> {
358 
359  java.io.File dest;
360  ProgressHandle progress;
361  SwingWorker<T, V> worker;
362  boolean source = false;
363 
376  public ExtractFscContentVisitor(java.io.File dest,
377  ProgressHandle progress, SwingWorker<T, V> worker, boolean source) {
378  this.dest = dest;
379  this.progress = progress;
380  this.worker = worker;
381  this.source = source;
382  }
383 
384  public ExtractFscContentVisitor(java.io.File dest) {
385  this.dest = dest;
386  }
387 
392  public static <T, V> void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker<T, V> worker) {
393  cntnt.accept(new ExtractFscContentVisitor<>(dest, progress, worker, true));
394  }
395 
396  @Override
397  public Void visit(File file) {
398  try {
399  ContentUtils.writeToFile(file, dest, progress, worker, source);
400  } catch (ReadContentInputStreamException ex) {
401  logger.log(Level.WARNING,
402  String.format("Error reading file '%s' (id=%d).",
403  file.getName(), file.getId()), ex); //NON-NLS
404  } catch (IOException ex) {
405  logger.log(Level.SEVERE,
406  String.format("Error extracting file '%s' (id=%d) to '%s'.",
407  file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
408  }
409  return null;
410  }
411 
412  @Override
413  public Void visit(LayoutFile file) {
414  try {
415  ContentUtils.writeToFile(file, dest, progress, worker, source);
416  } catch (ReadContentInputStreamException ex) {
417  logger.log(Level.WARNING,
418  String.format("Error reading file '%s' (id=%d).",
419  file.getName(), file.getId()), ex); //NON-NLS
420  } catch (IOException ex) {
421  logger.log(Level.SEVERE,
422  String.format("Error extracting unallocated content file '%s' (id=%d) to '%s'.",
423  file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
424  }
425  return null;
426  }
427 
428  @Override
429  public Void visit(DerivedFile file) {
430  try {
431  ContentUtils.writeToFile(file, dest, progress, worker, source);
432  } catch (ReadContentInputStreamException ex) {
433  logger.log(Level.WARNING,
434  String.format("Error reading file '%s' (id=%d).",
435  file.getName(), file.getId()), ex); //NON-NLS
436  } catch (IOException ex) {
437  logger.log(Level.SEVERE,
438  String.format("Error extracting derived file '%s' (id=%d) to '%s'.",
439  file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
440  }
441  return null;
442  }
443 
444  @Override
445  public Void visit(LocalFile file) {
446  try {
447  ContentUtils.writeToFile(file, dest, progress, worker, source);
448  } catch (ReadContentInputStreamException ex) {
449  logger.log(Level.WARNING,
450  String.format("Error reading file '%s' (id=%d).",
451  file.getName(), file.getId()), ex); //NON-NLS
452  } catch (IOException ex) {
453  logger.log(Level.SEVERE,
454  String.format("Error extracting local file '%s' (id=%d) to '%s'.",
455  file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
456  }
457  return null;
458  }
459 
460  @Override
461  public Void visit(SlackFile file) {
462  try {
463  ContentUtils.writeToFile(file, dest, progress, worker, source);
464  } catch (ReadContentInputStreamException ex) {
465  logger.log(Level.WARNING,
466  String.format("Error reading file '%s' (id=%d).",
467  file.getName(), file.getId()), ex); //NON-NLS
468  } catch (IOException ex) {
469  logger.log(Level.SEVERE,
470  String.format("Error extracting slack file '%s' (id=%d) to '%s'.",
471  file.getName(), file.getId(), dest.getAbsolutePath()), ex); //NON-NLS
472  }
473  return null;
474  }
475 
476  @Override
477  public Void visit(Directory dir) {
478  return visitDir(dir);
479  }
480 
481  @Override
482  public Void visit(VirtualDirectory dir) {
483  return visitDir(dir);
484  }
485 
486  @Override
487  public Void visit(LocalDirectory dir) {
488  return visitDir(dir);
489  }
490 
491  private java.io.File getFsContentDest(Content content) {
492  String path = dest.getAbsolutePath() + java.io.File.separator
493  + content.getName();
494  return new java.io.File(path);
495  }
496 
497  public Void visitDir(AbstractFile dir) {
498 
499  // don't extract . and .. directories
500  if (isDotDirectory(dir)) {
501  return null;
502  }
503 
504  dest.mkdir();
505 
506  try {
507  int numProcessed = 0;
508  // recurse on children
509  for (Content child : dir.getChildren()) {
510  if (child instanceof AbstractFile) { //ensure the directory's artifact children are ignored
511  java.io.File childFile = getFsContentDest(child);
512  ExtractFscContentVisitor<T, V> childVisitor
513  = new ExtractFscContentVisitor<>(childFile, progress, worker, false);
514  // If this is the source directory of an extract it
515  // will have a progress and worker, and will keep track
516  // of the progress bar's progress
517  if (worker != null && worker.isCancelled()) {
518  break;
519  }
520  if (progress != null && source) {
521  progress.progress(child.getName(), numProcessed);
522  }
523  child.accept(childVisitor);
524  numProcessed++;
525  }
526  }
527  } catch (TskCoreException ex) {
528  logger.log(Level.SEVERE,
529  "Trouble fetching children to extract.", ex); //NON-NLS
530  }
531 
532  return null;
533  }
534 
535  @Override
536  protected Void defaultVisit(Content content) {
537  throw new UnsupportedOperationException(NbBundle.getMessage(this.getClass(),
538  "ContentUtils.exception.msg",
539  content.getClass().getSimpleName()));
540  }
541  }
542 
550  @Deprecated
551  public static boolean shouldDisplayTimesInLocalTime() {
553  }
554 
555 }
static String getStringTime(long epochSeconds, TimeZone tzone)
static final SimpleDateFormat dateFormatter
ExtractFscContentVisitor(java.io.File dest, ProgressHandle progress, SwingWorker< T, V > worker, boolean source)
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, long startingOffset, long endingOffset)
static String getSystemName(Content content)
static String getStringTime(long epochSeconds, Content content)
static< T, V > void extract(Content cntnt, java.io.File dest, ProgressHandle progress, SwingWorker< T, V > worker)
static TimeZone getTimeZone(Content content)
static String getStringTimeISO8601(long epochSeconds, TimeZone tzone)
static final SimpleDateFormat dateFormatterISO8601
static final SystemNameVisitor systemName
synchronized static Logger getLogger(String name)
Definition: Logger.java:124
static String getStringTimeISO8601(long epochSeconds, Content c)
static void writeToFile(Content content, java.io.File outputFile)
static long writeToFile(Content content, java.io.File outputFile, Supplier< Boolean > cancelCheck)
static boolean isDotDirectory(AbstractFile dir)

Copyright © 2012-2021 Basis Technology. Generated on: Thu Sep 30 2021
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.