19 package org.sleuthkit.autopsy.modules.embeddedfileextractor;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.io.OutputStream;
25 import java.nio.file.Files;
26 import java.nio.file.Paths;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Date;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.logging.Level;
34 import net.sf.sevenzipjbinding.ArchiveFormat;
35 import static net.sf.sevenzipjbinding.ArchiveFormat.RAR;
36 import net.sf.sevenzipjbinding.ISequentialOutStream;
37 import net.sf.sevenzipjbinding.ISevenZipInArchive;
38 import net.sf.sevenzipjbinding.SevenZip;
39 import net.sf.sevenzipjbinding.SevenZipException;
40 import net.sf.sevenzipjbinding.SevenZipNativeInitializationException;
41 import net.sf.sevenzipjbinding.simple.ISimpleInArchive;
42 import net.sf.sevenzipjbinding.simple.ISimpleInArchiveItem;
43 import net.sf.sevenzipjbinding.ExtractOperationResult;
44 import org.netbeans.api.progress.ProgressHandle;
45 import org.openide.util.NbBundle;
46 import org.openide.util.NbBundle.Messages;
71 class SevenZipExtractor {
73 private static final Logger logger = Logger.getLogger(SevenZipExtractor.class.getName());
74 private IngestServices services = IngestServices.getInstance();
75 private final IngestJobContext context;
76 private final FileTypeDetector fileTypeDetector;
78 private static final String ENCRYPTION_FILE_LEVEL = NbBundle.getMessage(EmbeddedFileExtractorIngestModule.class,
79 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFileLevel");
80 private static final String ENCRYPTION_FULL = NbBundle.getMessage(EmbeddedFileExtractorIngestModule.class,
81 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.encryptionFull");
83 private static final int MAX_DEPTH = 4;
84 private static final int MAX_COMPRESSION_RATIO = 600;
85 private static final long MIN_COMPRESSION_RATIO_SIZE = 500 * 1000000L;
86 private static final long MIN_FREE_DISK_SPACE = 1 * 1000 * 1000000L;
88 private String moduleDirRelative;
89 private String moduleDirAbsolute;
91 private Blackboard blackboard;
93 private String getLocalRootAbsPath(String uniqueArchiveFileName) {
94 return moduleDirAbsolute + File.separator + uniqueArchiveFileName;
109 XRAR(
"application/x-rar-compressed");
114 this.mimeType = mimeType;
119 return this.mimeType;
124 SevenZipExtractor(
IngestJobContext context,
FileTypeDetector fileTypeDetector, String moduleDirRelative, String moduleDirAbsolute)
throws SevenZipNativeInitializationException {
125 if (!SevenZip.isInitializedSuccessfully() && (SevenZip.getLastInitializationException() == null)) {
126 SevenZip.initSevenZipFromPlatformJAR();
128 this.context = context;
129 this.fileTypeDetector = fileTypeDetector;
130 this.moduleDirRelative = moduleDirRelative;
131 this.moduleDirAbsolute = moduleDirAbsolute;
142 boolean isSevenZipExtractionSupported(AbstractFile file) {
143 String fileMimeType = fileTypeDetector.getMIMEType(file);
144 for (SupportedArchiveExtractionFormats mimeType : SupportedArchiveExtractionFormats.values()) {
145 if (mimeType.toString().equals(fileMimeType)) {
164 private boolean isZipBombArchiveItemCheck(AbstractFile archiveFile, ISimpleInArchiveItem archiveFileItem) {
166 final Long archiveItemSize = archiveFileItem.getSize();
169 if (archiveItemSize == null || archiveItemSize < MIN_COMPRESSION_RATIO_SIZE) {
173 final Long archiveItemPackedSize = archiveFileItem.getPackedSize();
175 if (archiveItemPackedSize == null || archiveItemPackedSize <= 0) {
176 logger.log(Level.WARNING,
"Cannot getting compression ratio, cannot detect if zipbomb: {0}, item: {1}",
new Object[]{archiveFile.getName(), archiveFileItem.getPath()});
180 int cRatio = (int) (archiveItemSize / archiveItemPackedSize);
182 if (cRatio >= MAX_COMPRESSION_RATIO) {
183 String itemName = archiveFileItem.getPath();
184 logger.log(Level.INFO,
"Possible zip bomb detected, compression ration: {0} for in archive item: {1}",
new Object[]{cRatio, itemName});
185 String msg = NbBundle.getMessage(SevenZipExtractor.class,
186 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnMsg", archiveFile.getName(), itemName);
189 path = archiveFile.getUniquePath();
190 }
catch (TskCoreException ex) {
191 path = archiveFile.getParentPath() + archiveFile.getName();
193 String details = NbBundle.getMessage(SevenZipExtractor.class,
194 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.isZipBombCheck.warnDetails", cRatio, path);
196 services.postMessage(IngestMessage.createWarningMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details));
202 }
catch (SevenZipException ex) {
203 logger.log(Level.WARNING,
"Error getting archive item size and cannot detect if zipbomb. ", ex);
216 private ArchiveFormat get7ZipOptions(AbstractFile archiveFile) {
218 String detectedFormat;
219 detectedFormat = archiveFile.getMIMEType();
221 if (detectedFormat == null) {
222 logger.log(Level.WARNING,
"Could not detect format for file: {0}", archiveFile);
225 String extension = archiveFile.getNameExtension();
226 if (
"rar".equals(extension))
235 }
else if (detectedFormat.contains(
"application/x-rar-compressed"))
256 private long getRootArchiveId(AbstractFile file)
throws TskCoreException {
257 long id = file.getId();
258 Content parentContent = file.getParent();
259 while (parentContent != null) {
260 id = parentContent.getId();
261 parentContent = parentContent.getParent();
280 private List<AbstractFile> getAlreadyExtractedFiles(AbstractFile archiveFile, String archiveFilePath)
throws TskCoreException, NoCurrentCaseException {
283 if (archiveFile.hasChildren() &&
new File(moduleDirAbsolute, EmbeddedFileExtractorIngestModule.getUniqueName(archiveFile)).exists()) {
284 return Case.getCurrentCaseThrows().getServices().getFileManager().findFilesByParentPath(getRootArchiveId(archiveFile), archiveFilePath);
286 return new ArrayList<>();
296 private String getArchiveFilePath(AbstractFile archiveFile) {
298 return archiveFile.getUniquePath();
299 }
catch (TskCoreException ex) {
300 return archiveFile.getParentPath() + archiveFile.getName();
310 private void makeLocalDirectories(String uniqueArchiveFileName) {
311 final String localRootAbsPath = getLocalRootAbsPath(uniqueArchiveFileName);
312 final File localRoot =
new File(localRootAbsPath);
313 if (!localRoot.exists()) {
330 private String getPathInArchive(ISimpleInArchiveItem item,
int itemNumber, AbstractFile archiveFile)
throws SevenZipException {
331 String pathInArchive = item.getPath();
333 if (pathInArchive == null || pathInArchive.isEmpty()) {
339 String archName = archiveFile.getName();
340 int dotI = archName.lastIndexOf(
".");
341 String useName = null;
343 String base = archName.substring(0, dotI);
344 String ext = archName.substring(dotI);
345 int colonIndex = ext.lastIndexOf(
":");
346 if (colonIndex != -1) {
349 ext = ext.substring(0, colonIndex);
356 useName = base +
".tar";
363 if (useName == null) {
364 pathInArchive =
"/" + archName +
"/" + Integer.toString(itemNumber);
366 pathInArchive =
"/" + useName;
368 String msg = NbBundle.getMessage(SevenZipExtractor.class,
369 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.unknownPath.msg",
370 getArchiveFilePath(archiveFile), pathInArchive);
371 logger.log(Level.WARNING, msg);
373 return pathInArchive;
380 private String getKeyAbstractFile(AbstractFile fileInDatabase) {
381 return fileInDatabase == null ? null : fileInDatabase.getParentPath() + fileInDatabase.getName();
388 private String getKeyFromUnpackedNode(UnpackedTree.UnpackedNode node, String archiveFilePath) {
389 return node == null ? null : archiveFilePath +
"/" + node.getFileName();
406 private SevenZipExtractor.UnpackedTree.UnpackedNode unpackNode(ISimpleInArchiveItem item, SevenZipExtractor.UnpackedTree.UnpackedNode unpackedNode, String password,
long freeDiskSpace, String uniqueExtractedName)
throws SevenZipException {
408 final String localAbsPath = moduleDirAbsolute + File.separator + uniqueExtractedName;
409 final String localRelPath = moduleDirRelative + File.separator + uniqueExtractedName;
410 final Date createTime = item.getCreationTime();
411 final Date accessTime = item.getLastAccessTime();
412 final Date writeTime = item.getLastWriteTime();
413 final long createtime = createTime == null ? 0L : createTime.getTime() / 1000;
414 final long modtime = writeTime == null ? 0L : writeTime.getTime() / 1000;
415 final long accesstime = accessTime == null ? 0L : accessTime.getTime() / 1000;
416 SevenZipExtractor.UnpackStream unpackStream = null;
417 boolean isDir = item.isFolder();
422 if (item.getSize() != null) {
423 unpackStream =
new SevenZipExtractor.KnownSizeUnpackStream(localAbsPath, item.getSize());
425 unpackStream =
new SevenZipExtractor.UnknownSizeUnpackStream(localAbsPath, freeDiskSpace);
427 ExtractOperationResult result;
428 if (password == null) {
429 result = item.extractSlow(unpackStream);
431 result = item.extractSlow(unpackStream, password);
433 if (result != ExtractOperationResult.OK) {
434 logger.log(Level.WARNING,
"Extraction of : {0} encountered error {1}",
new Object[]{localAbsPath, result});
438 }
catch (SevenZipException e) {
440 logger.log(Level.WARNING,
"Could not extract file from archive: " + localAbsPath, e);
442 if (unpackStream != null) {
444 unpackedNode.addDerivedInfo(unpackStream.getSize(), !isDir,
445 0L, createtime, accesstime, modtime, localRelPath);
446 unpackStream.close();
450 unpackedNode.addDerivedInfo(0, !isDir, 0L, createtime, accesstime, modtime, localRelPath);
464 void unpack(AbstractFile archiveFile, ConcurrentHashMap<Long, Archive> depthMap) {
465 unpack(archiveFile, depthMap, null);
479 @Messages({
"SevenZipExtractor.indexError.message=Failed to index encryption detected artifact for keyword search."})
480 boolean unpack(AbstractFile archiveFile, ConcurrentHashMap<Long, Archive> depthMap, String password) {
481 boolean unpackSuccessful =
true;
482 boolean hasEncrypted =
false;
483 boolean fullEncryption =
true;
484 boolean progressStarted =
false;
485 int processedItems = 0;
486 final String archiveFilePath = getArchiveFilePath(archiveFile);
487 final String escapedArchiveFilePath = FileUtil.escapeFileName(archiveFilePath);
488 HashMap<String, ZipFileStatusWrapper> statusMap =
new HashMap<>();
489 List<AbstractFile> unpackedFiles = Collections.<AbstractFile>emptyList();
490 ISevenZipInArchive inArchive = null;
492 SevenZipContentReadStream stream = null;
493 final ProgressHandle progress = ProgressHandle.createHandle(Bundle.EmbeddedFileExtractorIngestModule_ArchiveExtractor_moduleName());
495 final long archiveId = archiveFile.getId();
498 blackboard = Case.getCurrentCaseThrows().getServices().getBlackboard();
499 }
catch (NoCurrentCaseException ex) {
500 logger.log(Level.INFO,
"Exception while getting open case.", ex);
501 unpackSuccessful =
false;
502 return unpackSuccessful;
506 List<AbstractFile> existingFiles = getAlreadyExtractedFiles(archiveFile, archiveFilePath);
507 for (AbstractFile file : existingFiles) {
508 statusMap.put(getKeyAbstractFile(file),
new ZipFileStatusWrapper(file, ZipFileStatus.EXISTS));
510 }
catch (TskCoreException e) {
511 logger.log(Level.INFO,
"Error checking if file already has been processed, skipping: {0}", escapedArchiveFilePath);
512 unpackSuccessful =
false;
513 return unpackSuccessful;
514 }
catch (NoCurrentCaseException ex) {
515 logger.log(Level.INFO,
"No open case was found while trying to unpack the archive file {0}", escapedArchiveFilePath);
516 unpackSuccessful =
false;
517 return unpackSuccessful;
519 parentAr = depthMap.get(archiveId);
520 if (parentAr == null) {
521 parentAr =
new Archive(archiveId, 0);
522 depthMap.put(archiveId, parentAr);
523 }
else if (parentAr.getDepth() == MAX_DEPTH) {
524 String msg = NbBundle.getMessage(SevenZipExtractor.class,
525 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnMsg.zipBomb", archiveFile.getName());
526 String details = NbBundle.getMessage(SevenZipExtractor.class,
527 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.warnDetails.zipBomb",
528 parentAr.getDepth(), escapedArchiveFilePath);
530 services.postMessage(IngestMessage.createWarningMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details));
531 unpackSuccessful =
false;
532 return unpackSuccessful;
535 stream =
new SevenZipContentReadStream(
new ReadContentInputStream(archiveFile));
539 ArchiveFormat options = get7ZipOptions(archiveFile);
540 if (password == null) {
541 inArchive = SevenZip.openInArchive(options, stream);
543 inArchive = SevenZip.openInArchive(options, stream, password);
545 int numItems = inArchive.getNumberOfItems();
546 logger.log(Level.INFO,
"Count of items in archive: {0}: {1}",
new Object[]{escapedArchiveFilePath, numItems});
547 progress.start(numItems);
548 progressStarted =
true;
549 final ISimpleInArchive simpleInArchive = inArchive.getSimpleInterface();
552 final String uniqueArchiveFileName = FileUtil.escapeFileName(EmbeddedFileExtractorIngestModule.getUniqueName(archiveFile));
554 makeLocalDirectories(uniqueArchiveFileName);
555 }
catch (SecurityException e) {
556 logger.log(Level.SEVERE,
"Error setting up output path for archive root: {0}", getLocalRootAbsPath(uniqueArchiveFileName));
558 unpackSuccessful =
false;
559 return unpackSuccessful;
563 SevenZipExtractor.UnpackedTree unpackedTree =
new SevenZipExtractor.UnpackedTree(moduleDirRelative +
"/" + uniqueArchiveFileName, archiveFile);
567 freeDiskSpace = services.getFreeDiskSpace();
568 }
catch (NullPointerException ex) {
571 freeDiskSpace = IngestMonitor.DISK_FREE_SPACE_UNKNOWN;
576 for (ISimpleInArchiveItem item : simpleInArchive.getArchiveItems()) {
577 String pathInArchive = getPathInArchive(item, itemNumber, archiveFile);
583 if (isZipBombArchiveItemCheck(archiveFile, item)) {
584 unpackSuccessful =
false;
585 return unpackSuccessful;
587 SevenZipExtractor.UnpackedTree.UnpackedNode unpackedNode = unpackedTree.addNode(pathInArchive);
589 progress.progress(archiveFile.getName() +
": " + item.getPath(), processedItems);
591 final boolean isEncrypted = item.isEncrypted();
593 if (isEncrypted && password == null) {
594 logger.log(Level.WARNING,
"Skipping encrypted file in archive: {0}", pathInArchive);
596 unpackSuccessful =
false;
599 fullEncryption =
false;
605 if (freeDiskSpace != IngestMonitor.DISK_FREE_SPACE_UNKNOWN && item.getSize() != null && item.getSize() > 0) {
606 long newDiskSpace = freeDiskSpace - item.getSize();
607 if (newDiskSpace < MIN_FREE_DISK_SPACE) {
608 String msg = NbBundle.getMessage(SevenZipExtractor.class,
609 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.msg",
610 escapedArchiveFilePath, item.getPath());
611 String details = NbBundle.getMessage(SevenZipExtractor.class,
612 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.notEnoughDiskSpace.details");
614 services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details));
615 logger.log(Level.INFO,
"Skipping archive item due to insufficient disk space: {0}, {1}",
new String[]{escapedArchiveFilePath, item.getPath()});
616 logger.log(Level.INFO,
"Available disk space: {0}",
new Object[]{freeDiskSpace});
617 unpackSuccessful =
false;
621 freeDiskSpace = newDiskSpace;
624 final String uniqueExtractedName = FileUtil.escapeFileName(uniqueArchiveFileName + File.separator + (item.getItemIndex() / 1000) + File.separator + item.getItemIndex() +
"_" +
new File(pathInArchive).getName());
627 File localFile =
new java.io.File(moduleDirAbsolute + File.separator + uniqueExtractedName);
629 if (!localFile.exists()) {
631 if (item.isFolder()) {
634 localFile.getParentFile().mkdirs();
636 localFile.createNewFile();
637 }
catch (IOException e) {
638 logger.log(Level.SEVERE,
"Error creating extracted file: " + localFile.getAbsolutePath(), e);
641 }
catch (SecurityException e) {
642 logger.log(Level.SEVERE,
"Error setting up output path for unpacked file: {0}", pathInArchive);
647 if (localFile.exists() ==
false) {
651 unpackedNode = unpackNode(item, unpackedNode, password,
652 freeDiskSpace, uniqueExtractedName);
653 if (unpackedNode == null) {
654 unpackSuccessful =
false;
663 unpackedTree.updateOrAddFileToCaseRec(statusMap, archiveFilePath);
664 unpackedFiles = unpackedTree.getAllFileObjects();
666 for (AbstractFile unpackedFile : unpackedFiles) {
667 if (unpackedFile == null) {
670 if (isSevenZipExtractionSupported(unpackedFile)) {
671 Archive child =
new Archive(unpackedFile.getId(), parentAr.getDepth() + 1);
672 parentAr.addChild(child);
673 depthMap.put(unpackedFile.getId(), child);
677 }
catch (TskCoreException | NoCurrentCaseException e) {
678 logger.log(Level.SEVERE,
"Error populating complete derived file hierarchy from the unpacked dir structure", e);
682 }
catch (SevenZipException ex) {
683 logger.log(Level.WARNING,
"Error unpacking file: " + archiveFile, ex);
687 if (archiveFile.isMetaFlagSet(TskData.TSK_FS_META_FLAG_ENUM.ALLOC)) {
688 String msg = NbBundle.getMessage(SevenZipExtractor.class,
689 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.msg",
690 archiveFile.getName());
691 String details = NbBundle.getMessage(SevenZipExtractor.class,
692 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.errUnpacking.details",
693 escapedArchiveFilePath, ex.getMessage());
694 services.postMessage(IngestMessage.createErrorMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details));
697 if (inArchive != null) {
700 }
catch (SevenZipException e) {
701 logger.log(Level.SEVERE,
"Error closing archive: " + archiveFile, e);
705 if (stream != null) {
708 }
catch (IOException ex) {
709 logger.log(Level.SEVERE,
"Error closing stream after unpacking archive: " + archiveFile, ex);
714 if (progressStarted) {
721 String encryptionType = fullEncryption ? ENCRYPTION_FULL : ENCRYPTION_FILE_LEVEL;
723 BlackboardArtifact artifact = archiveFile.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED);
724 artifact.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, EmbeddedFileExtractorModuleFactory.getModuleName(), encryptionType));
728 blackboard.indexArtifact(artifact);
729 }
catch (Blackboard.BlackboardException ex) {
730 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + artifact.getArtifactID(), ex);
731 MessageNotifyUtil.Notify.error(
732 Bundle.SevenZipExtractor_indexError_message(), artifact.getDisplayName());
735 services.fireModuleDataEvent(
new ModuleDataEvent(EmbeddedFileExtractorModuleFactory.getModuleName(), BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED));
736 }
catch (TskCoreException ex) {
737 logger.log(Level.SEVERE,
"Error creating blackboard artifact for encryption detected for file: " + escapedArchiveFilePath, ex);
740 String msg = NbBundle.getMessage(SevenZipExtractor.class,
741 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.encrFileDetected.msg");
742 String details = NbBundle.getMessage(SevenZipExtractor.class,
743 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.unpack.encrFileDetected.details",
744 archiveFile.getName(), EmbeddedFileExtractorModuleFactory.getModuleName());
745 services.postMessage(IngestMessage.createWarningMessage(EmbeddedFileExtractorModuleFactory.getModuleName(), msg, details));
749 if (!unpackedFiles.isEmpty()) {
751 services.fireModuleContentEvent(
new ModuleContentEvent(archiveFile));
752 if (context != null) {
753 context.addFilesToJob(unpackedFiles);
756 return unpackSuccessful;
762 private abstract static class UnpackStream implements ISequentialOutStream {
770 output =
new EncodedFileOutputStream(
new FileOutputStream(localAbsPath), TskData.EncodingType.XOR1);
771 }
catch (IOException ex) {
772 logger.log(Level.SEVERE,
"Error writing extracted file: " + localAbsPath, ex);
777 public abstract long getSize();
779 OutputStream getOutput() {
783 String getLocalAbsPath() {
788 if (output != null) {
792 }
catch (IOException e) {
793 logger.log(Level.SEVERE,
"Error closing unpack stream for file: {0}", localAbsPath);
819 public int write(byte[] bytes)
throws SevenZipException {
825 getOutput().write(bytes);
829 this.bytesWritten += bytes.length;
830 this.freeDiskSpace -= bytes.length;
832 this.outOfSpace =
true;
833 logger.log(Level.INFO, NbBundle.getMessage(
834 SevenZipExtractor.class,
835 "EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
836 throw new SevenZipException(
837 NbBundle.getMessage(SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.noSpace.msg"));
839 }
catch (IOException ex) {
840 throw new SevenZipException(
841 NbBundle.getMessage(SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
842 getLocalAbsPath()), ex);
849 if (getOutput() != null) {
853 if (this.outOfSpace) {
854 Files.delete(Paths.get(getLocalAbsPath()));
856 }
catch (IOException e) {
857 logger.log(Level.SEVERE,
"Error closing unpack stream for file: {0}", getLocalAbsPath());
881 public int write(byte[] bytes)
throws SevenZipException {
883 getOutput().write(bytes);
884 }
catch (IOException ex) {
885 throw new SevenZipException(
886 NbBundle.getMessage(SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackStream.write.exception.msg",
887 getLocalAbsPath()), ex);
911 UnpackedTree(String localPathRoot, AbstractFile archiveFile) {
913 this.rootNode.setFile(archiveFile);
914 this.rootNode.setFileName(archiveFile.getName());
915 this.rootNode.setLocalRelPath(localPathRoot);
928 String[] toks = filePath.split(
"[\\/\\\\]");
929 List<String> tokens =
new ArrayList<>();
930 for (
int i = 0; i < toks.length; ++i) {
931 if (!toks[i].isEmpty()) {
935 return addNode(rootNode, tokens);
948 if (tokenPath.isEmpty()) {
953 String childName = tokenPath.remove(0);
958 parent.addChild(child);
962 return addNode(child, tokenPath);
971 List<AbstractFile> getRootFileObjects() {
972 List<AbstractFile> ret =
new ArrayList<>();
973 for (UnpackedNode child : rootNode.getChildren()) {
974 ret.add(child.getFile());
985 List<AbstractFile> getAllFileObjects() {
986 List<AbstractFile> ret =
new ArrayList<>();
987 for (UnpackedNode child : rootNode.getChildren()) {
994 list.add(parent.getFile());
1004 void updateOrAddFileToCaseRec(HashMap<String, ZipFileStatusWrapper> statusMap, String archiveFilePath)
throws TskCoreException,
NoCurrentCaseException {
1006 for (UnpackedNode child : rootNode.getChildren()) {
1007 updateOrAddFileToCaseRec(child, fileManager, statusMap, archiveFilePath);
1028 String nameInDatabase = getKeyFromUnpackedNode(node, archiveFilePath);
1029 ZipFileStatusWrapper existingFile = nameInDatabase == null ? null : statusMap.get(nameInDatabase);
1030 if (existingFile == null) {
1031 df = fileManager.
addDerivedFile(node.getFileName(), node.getLocalRelPath(), node.getSize(),
1032 node.getCtime(), node.getCrtime(), node.getAtime(), node.getMtime(),
1034 "",
"", TskData.EncodingType.XOR1);
1037 String key = getKeyAbstractFile(existingFile.
getFile());
1040 statusMap.put(key, existingFile);
1044 String mimeType = existingFile.
getFile().getMIMEType().equalsIgnoreCase(
"application/octet-stream") ? null : existingFile.
getFile().getMIMEType();
1046 node.getCtime(), node.getCrtime(), node.getAtime(), node.getMtime(),
1048 "",
"", TskData.EncodingType.XOR1);
1052 df = (DerivedFile) existingFile.
getFile();
1056 }
catch (TskCoreException ex) {
1057 logger.log(Level.SEVERE,
"Error adding a derived file to db:" + node.getFileName(), ex);
1058 throw new TskCoreException(
1059 NbBundle.getMessage(SevenZipExtractor.class,
"EmbeddedFileExtractorIngestModule.ArchiveExtractor.UnpackedTree.exception.msg",
1060 node.getFileName()), ex);
1064 updateOrAddFileToCaseRec(child, fileManager, statusMap, getKeyFromUnpackedNode(node, archiveFilePath));
1075 private final List<UnpackedNode>
children =
new ArrayList<>();
1076 private String localRelPath =
"";
1078 private long ctime, crtime, atime, mtime;
1090 this.localRelPath = parent.getLocalRelPath() + File.separator +
fileName;
1109 void setFileName(String fileName) {
1118 void addChild(UnpackedNode child) {
1119 children.add(child);
1128 List<UnpackedNode> getChildren() {
1137 UnpackedNode getParent() {
1141 void addDerivedInfo(
long size,
1143 long ctime,
long crtime,
long atime,
long mtime, String relLocalPath) {
1147 this.crtime = crtime;
1150 this.localRelPath = relLocalPath;
1153 void setFile(AbstractFile file) {
1164 UnpackedNode getChild(String childFileName) {
1165 UnpackedNode ret = null;
1166 for (UnpackedNode child : children) {
1167 if (child.getFileName().equals(childFileName)) {
1175 String getFileName() {
1179 AbstractFile getFile() {
1183 String getLocalRelPath() {
1193 void setLocalRelPath(String localRelativePath) {
1194 localRelPath = localRelativePath;
1201 boolean isIsFile() {
1211 static class Archive {
1214 private final int depth;
1215 private final long objectId;
1216 private final List<Archive> children;
1227 Archive(
long objectId,
int depth) {
1228 this.objectId = objectId;
1229 this.children =
new ArrayList<>();
1239 void addChild(Archive child) {
1240 children.add(child);
1248 long getObjectId() {
1281 abstractFile = file;
FileManager getFileManager()
synchronized DerivedFile addDerivedFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, Content parentObj, String rederiveDetails, String toolName, String toolVersion, String otherDetails, TskData.EncodingType encodingType)
static final int DISK_FREE_SPACE_UNKNOWN
static Case getCurrentCaseThrows()
synchronized DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, String mimeType, String rederiveDetails, String toolName, String toolVersion, String otherDetails, TskData.EncodingType encodingType)