/* * 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.experimental.autoingest; import java.io.File; import java.io.FilenameFilter; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import org.sleuthkit.autopsy.casemodule.CaseMetadata; import org.sleuthkit.autopsy.casemodule.GeneralFilter; final class PathUtils { private static final List<String> CASE_METADATA_FILE_EXTS = Arrays.asList(new String[]{CaseMetadata.getFileExtension()}); private static final GeneralFilter caseMetadataFileFilter = new GeneralFilter(CASE_METADATA_FILE_EXTS, "Autopsy Case File"); /** * Searches a given folder for the most recently modified case folder for a * case. * * @param folderToSearch The folder to be searched. * @param caseName The name of the case for which a case folder is to * be found. * * @return The path of the case folder, or null if it is not found. */ static Path findCaseDirectory(Path folderToSearch, String caseName) { File searchFolder = new File(folderToSearch.toString()); if (!searchFolder.isDirectory()) { return null; } Path caseFolderPath = null; String[] candidateFolders = searchFolder.list(new CaseFolderFilter(caseName)); long mostRecentModified = 0; for (String candidateFolder : candidateFolders) { File file = new File(candidateFolder); if (file.lastModified() >= mostRecentModified) { mostRecentModified = file.lastModified(); caseFolderPath = Paths.get(folderToSearch.toString(), file.getPath()); } } return caseFolderPath; } /** * Gets a listing of case folders in a given folder. * * @param folderToSearch The path of the folder to search. * * @return A list of the output case folder paths. */ static List<Path> findCaseFolders(Path folderToSearch) { // RJCTODO: Rename File searchFolder = new File(folderToSearch.toString()); if (!searchFolder.isDirectory()) { return Collections.emptyList(); } String[] caseFolders = searchFolder.list(new CaseFolderFilter(null)); List<Path> caseFolderPaths = new ArrayList<>(); for (String path : caseFolders) { caseFolderPaths.add(Paths.get(folderToSearch.toString(), path)); } return caseFolderPaths; } /** * Determines whether or not there is a case metadata file in a given * folder. * * @param folderPath Path to the folder to search. * * @return True or false. */ static boolean hasCaseMetadataFile(Path folderPath) { /** * TODO: If need be, this can be rewritten without the FilenameFilter so * that it does not necessarily visit every file in the folder. */ File folder = folderPath.toFile(); if (!folder.isDirectory()) { return false; } String[] caseDataFiles = folder.list((File folder1, String fileName) -> { File file = new File(folder1, fileName); if (file.isFile()) { return caseMetadataFileFilter.accept(file); } return false; }); return caseDataFiles.length != 0; } /** * Extracts the case name from a case folder path. * * @param caseFolderPath A case folder path. * * @return A case name, with the time stamp suffix removed. */ static String caseNameFromCaseDirectoryPath(Path caseFolderPath) { String caseName = caseFolderPath.getFileName().toString(); if (caseName.length() > TimeStampUtils.getTimeStampLength()) { return caseName.substring(0, caseName.length() - TimeStampUtils.getTimeStampLength()); } else { return caseName; } } /** * Creates a case folder path. Does not create the folder described by the * path. * * @param caseFoldersPath The root case folders path. * @param caseName The name of the case. * * @return A case folder path with a time stamp suffix. */ static Path createCaseFolderPath(Path caseFoldersPath, String caseName) { // RJCTODO: Rename String folderName = caseName + "_" + TimeStampUtils.createTimeStamp(); return Paths.get(caseFoldersPath.toString(), folderName); } private static class CaseFolderFilter implements FilenameFilter { private final String caseName; CaseFolderFilter(String caseName) { this.caseName = caseName; } @Override public boolean accept(File folder, String fileName) { File file = new File(folder, fileName); if (file.isDirectory() && fileName.length() > TimeStampUtils.getTimeStampLength()) { Path filePath = Paths.get(file.getPath()); if (TimeStampUtils.endsWithTimeStamp(fileName)) { if (null != caseName) { String fileNamePrefix = fileName.substring(0, fileName.length() - TimeStampUtils.getTimeStampLength()); if (fileNamePrefix.equals(caseName)) { return hasCaseMetadataFile(filePath); } } else { return hasCaseMetadataFile(filePath); } } } return false; } } /** * Supress creation of instances of this class. */ private PathUtils() { } }