diff --git a/bindings/java/src/org/sleuthkit/datamodel/FileManager.java b/bindings/java/src/org/sleuthkit/datamodel/FileManager.java new file mode 100644 index 0000000000000000000000000000000000000000..e285708c5bca99f9c7c643f40bb6b3d18eb0ae72 --- /dev/null +++ b/bindings/java/src/org/sleuthkit/datamodel/FileManager.java @@ -0,0 +1,111 @@ +/* + * SleuthKit Java Bindings + * + * Copyright 2021 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.datamodel; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.List; +import java.util.Objects; + +/** + * Utility class for file-based database queries. + */ +public class FileManager { + + private final SleuthkitCase skCase; + + /** + * Constructs a FileManager. + * + * @param casedb The case database. + */ + FileManager(SleuthkitCase skCase) { + this.skCase = Objects.requireNonNull(skCase, "Cannot create Blackboard for null SleuthkitCase"); + } + + /** + * Find all files with the exact given name and parentId. + * + * @param parentId Id of the parent folder to search. + * @param name Exact file name to match. + * + * @return A list of matching files. + * + * @throws TskCoreException + */ + public List<AbstractFile> findFilesExactName(long parentId, String name) throws TskCoreException { + String query = "SELECT tsk_files.* FROM tsk_files JOIN tsk_objects ON tsk_objects.obj_id = tsk_files.obj_id WHERE par_obj_id = ? AND name = ?"; + skCase.acquireSingleUserCaseReadLock(); + try (SleuthkitCase.CaseDbConnection connection = skCase.getConnection()) { + PreparedStatement statement = connection.getPreparedStatement(query, Statement.RETURN_GENERATED_KEYS); + statement.clearParameters(); + statement.setLong(1, parentId); + statement.setString(2, name); + try (ResultSet rs = connection.executeQuery(statement)) { + return skCase.resultSetToAbstractFiles(rs, connection); + } + } catch (SQLException ex) { + throw new TskCoreException("SQLException thrown when calling query: " + query + " for parentID = " + parentId + " and name " + name, ex); + } finally { + skCase.releaseSingleUserCaseReadLock(); + } + } + + /** + * Find all files with the exact given name and exact parent path. + * + * @param dataSource The data source to search within. + * @param name Exact file name to match. + * @param path Exact parent path. + * + * @return A list of matching files. + * + * @throws TskCoreException + */ + public List<AbstractFile> findFilesExactNameExactPath(Content dataSource, String name, String path) throws TskCoreException { + + // Database paths will always start and end with a forward slash, so add those if not present + String normalizedPath = path; + if (!normalizedPath.startsWith("/")) { + normalizedPath = "/" + normalizedPath; + } + if (!normalizedPath.endsWith("/")) { + normalizedPath = normalizedPath + "/"; + } + + String query = "SELECT tsk_files.* FROM tsk_files JOIN tsk_objects ON tsk_objects.obj_id = tsk_files.obj_id WHERE parent_path = ? AND name = ? AND data_source_obj_id = ?"; + skCase.acquireSingleUserCaseReadLock(); + try (SleuthkitCase.CaseDbConnection connection = skCase.getConnection()) { + PreparedStatement statement = connection.getPreparedStatement(query, Statement.RETURN_GENERATED_KEYS); + statement.clearParameters(); + statement.setString(1, normalizedPath); + statement.setString(2, name); + statement.setLong(3, dataSource.getId()); + try (ResultSet rs = connection.executeQuery(statement)) { + return skCase.resultSetToAbstractFiles(rs, connection); + } + } catch (SQLException ex) { + throw new TskCoreException("SQLException thrown when calling query: " + query + " for parent path = " + path + " and name " + name, ex); + } finally { + skCase.releaseSingleUserCaseReadLock(); + } + } +} diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java index 350ad81cd1a7896ca7abd2b310861498ca9a0ff2..9d522eb7b2da0906411a3c68e4b04ba3e51827fa 100755 --- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java +++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java @@ -222,6 +222,7 @@ public class SleuthkitCase { private TimelineManager timelineMgr; private Blackboard blackboard; private CaseDbAccessManager dbAccessManager; + private FileManager fileManager; private TaggingManager taggingMgr; private ScoringManager scoringManager; private OsAccountRealmManager osAccountRealmManager; @@ -403,6 +404,7 @@ private void init() throws Exception { } blackboard = new Blackboard(this); + fileManager = new FileManager(this); communicationsMgr = new CommunicationsManager(this); timelineMgr = new TimelineManager(this); dbAccessManager = new CaseDbAccessManager(this); @@ -493,6 +495,15 @@ public CommunicationsManager getCommunicationsManager() throws TskCoreException public Blackboard getBlackboard() { return blackboard; } + + /** + * Gets the file manager for this case. + * + * @return The per case FileManager object. + */ + public FileManager getFileManager() { + return fileManager; + } /** * Gets the communications manager for this case. @@ -9606,7 +9617,7 @@ void deleteDataSource(long dataSourceObjectId) throws TskCoreException { * @throws SQLException Thrown if there is a problem iterating through the * record set. */ - private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnection connection) throws SQLException { + List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnection connection) throws SQLException { ArrayList<AbstractFile> results = new ArrayList<AbstractFile>(); try { while (rs.next()) {