19 package org.sleuthkit.autopsy.coreutils;
22 import java.io.IOException;
23 import java.sql.Connection;
24 import java.sql.DriverManager;
25 import java.sql.ResultSet;
26 import java.sql.SQLException;
27 import java.sql.Statement;
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.List;
31 import java.util.logging.Level;
71 AbstractFile getAbstractFile() {
82 this.dbAbstractFile = appSQLiteDBFileBundle.getAbstractFile();
84 Class.forName(
"org.sqlite.JDBC");
85 connection = DriverManager.getConnection(
"jdbc:sqlite:" + appSQLiteDBFileBundle.getFileCopy().getPath());
86 statement = connection.createStatement();
109 String dbFileName,
boolean matchExactName, String parentPathSubstr) {
111 List<AppSQLiteDB> appDbs =
new ArrayList<>();
113 Collection<AppSQLiteDBFileBundle> dbFileBundles =
findAndCopySQLiteDB(dataSource, dbFileName, matchExactName, parentPathSubstr,
false);
114 dbFileBundles.forEach((dbFileBundle) -> {
117 appDbs.add(appSQLiteDB);
118 }
catch (ClassNotFoundException | SQLException ex) {
119 Logger.
getLogger(
AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format(
"Failed to open a DB connection for file = '%s' and path = '%s'.", dbFileBundle.dbAbstractFile.getName(), dbFileBundle.getFileCopy().getPath()), ex);
122 }
catch (TskCoreException ex) {
123 Logger.
getLogger(
AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format(
"Error finding App database files with name = '%s' and path = '%s'.", dbFileName, parentPathSubstr), ex);
151 String dbPath, String dbAlias)
throws SQLException {
154 Collection<AppSQLiteDBFileBundle> dbFileBundles =
findAndCopySQLiteDB(dataSource, dbName,
true, dbPath,
true);
155 if (!dbFileBundles.isEmpty()) {
157 String attachDbSql = String.format(
"ATTACH DATABASE '%s' AS '%s'", dbFileBundle.getFileCopy().getPath(), dbAlias);
158 statement.executeUpdate(attachDbSql);
160 return dbFileBundle.getAbstractFile();
162 }
catch (TskCoreException ex) {
163 Logger.
getLogger(
AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format(
"Error attaching to App database files with name = '%s' and path = '%s'.", dbName, dbPath), ex);
186 private static Collection<AppSQLiteDBFileBundle>
findAndCopySQLiteDB(DataSource dataSource, String dbName,
187 boolean matchExactName, String dbPath,
boolean matchExactPath)
throws TskCoreException {
193 throw new TskCoreException(
"Failed to get current case.", ex);
196 List<AppSQLiteDBFileBundle> dbFileBundles =
new ArrayList<>();
198 String localDiskPath =
"";
201 String parentPath = dbPath.replace(
"\\",
"/");
202 parentPath = SleuthkitCase.escapeSingleQuotes(parentPath);
205 if (matchExactName) {
206 whereClause = String.format(
"LOWER(name) = LOWER('%s')", dbName);
208 whereClause = String.format(
"LOWER(name) LIKE LOWER('%%%s%%') AND LOWER(name) NOT LIKE LOWER('%%journal%%')", dbName);
210 if (matchExactPath) {
211 whereClause += String.format(
" AND LOWER(parent_path) = LOWER('%s')", parentPath);
213 whereClause += String.format(
" AND LOWER(parent_path) LIKE LOWER('%%%s%%')", parentPath);
215 whereClause += String.format(
" AND data_source_obj_id = %s", dataSource.getId());
217 List<AbstractFile> absFiles = skCase.findAllFilesWhere(whereClause);
218 for (AbstractFile absFile : absFiles) {
221 + File.separator + absFile.getId() + absFile.getName();
222 File jFile =
new java.io.File(localDiskPath);
223 fileId = absFile.getId();
231 dbFileBundles.add(dbFileBundle);
233 }
catch (ReadContentInputStream.ReadContentInputStreamException ex) {
234 Logger.
getLogger(
AppSQLiteDB.class.getName()).log(Level.WARNING, String.format(
"Error reading content from file '%s' (id=%d).", absFile.getName(), fileId), ex);
236 Logger.
getLogger(
AppSQLiteDB.class.getName()).log(Level.SEVERE, String.format(
"Error creating AppSQLiteDB for file '%s' (id=%d) to copied to '%s'.", absFile.getName(), fileId, localDiskPath), ex);
240 return dbFileBundles;
251 String detachDbSql = String.format(
"DETACH DATABASE '%s'", dbAlias);
252 statement.executeUpdate(detachDbSql);
265 public ResultSet
runQuery(String queryStr)
throws SQLException {
266 ResultSet resultSet = null;
268 if (null != queryStr) {
269 resultSet = statement.executeQuery(queryStr);
284 }
catch (SQLException e) {
285 logger.log(Level.SEVERE,
"Error closing the database", e);
298 public boolean columnExists(String tableName, String columnName)
throws TskCoreException {
301 Statement colExistsStatement = null;
302 ResultSet resultSet = null;
304 colExistsStatement = connection.createStatement();
305 String tableInfoQuery =
"PRAGMA table_info(%s)";
306 resultSet = colExistsStatement.executeQuery(String.format(tableInfoQuery, tableName));
307 while (resultSet.next()) {
308 if (resultSet.getString(
"name").equalsIgnoreCase(columnName)) {
313 }
catch (SQLException ex) {
314 throw new TskCoreException(
"Error checking if column " + columnName +
"exists ", ex);
316 if (resultSet != null) {
319 }
catch (SQLException ex2) {
320 logger.log(Level.WARNING,
"Failed to close resultset after checking column", ex2);
323 if (colExistsStatement != null) {
325 colExistsStatement.close();
326 }
catch (SQLException ex2) {
327 logger.log(Level.SEVERE,
"Error closing Statement", ex2);
342 public boolean tableExists(String tableName)
throws TskCoreException {
345 Statement tableExistsStatement = null;
346 ResultSet resultSet = null;
349 tableExistsStatement = connection.createStatement();
350 resultSet = tableExistsStatement.executeQuery(
"SELECT name FROM sqlite_master WHERE type='table'");
351 while (resultSet.next()) {
352 if (resultSet.getString(
"name").equalsIgnoreCase(tableName)) {
357 }
catch (SQLException ex) {
358 throw new TskCoreException(
"Error checking if table " + tableName +
"exists ", ex);
360 if (resultSet != null) {
363 }
catch (SQLException ex2) {
364 logger.log(Level.WARNING,
"Failed to close resultset after checking table", ex2);
367 if (tableExistsStatement != null) {
369 tableExistsStatement.close();
370 }
catch (SQLException ex2) {
371 logger.log(Level.SEVERE,
"Error closing Statement", ex2);
394 if(sqliteFile.getParentPath().equalsIgnoreCase(
"/$carvedfiles/")) {
403 List<AbstractFile> metaFiles = fileManager.
findFilesExactName(sqliteFile.getParent().getId(), metaFileName);
405 if (metaFiles != null) {
406 for (AbstractFile metaFile : metaFiles) {
408 + File.separator + sqliteFile.getId() + metaFile.getName();
409 File localMetaFile =
new File(localDiskPath);
410 if (!localMetaFile.exists()) {
FileManager getFileManager()
boolean tableExists(String tableName)
String getTempDirectory()
static void findAndCopySQLiteMetaFile(AbstractFile sqliteFile, String metaFileName)
static< T > long writeToFile(Content content, java.io.File outputFile, ProgressHandle progress, Future< T > worker, boolean source)
void detachDatabase(String dbAlias)
static Collection< AppSQLiteDB > findAppDatabases(DataSource dataSource, String dbFileName, boolean matchExactName, String parentPathSubstr)
AbstractFile attachDatabase(DataSource dataSource, String dbName, String dbPath, String dbAlias)
final Connection connection
AppSQLiteDB(AppSQLiteDBFileBundle appSQLiteDBFileBundle)
static Collection< AppSQLiteDBFileBundle > findAndCopySQLiteDB(DataSource dataSource, String dbName, boolean matchExactName, String dbPath, boolean matchExactPath)
SleuthkitCase getSleuthkitCase()
boolean columnExists(String tableName, String columnName)
final Statement statement
ResultSet runQuery(String queryStr)
List< AbstractFile > findFilesExactName(long parentId, String name)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
final AbstractFile dbAbstractFile
final AbstractFile dbAbstractFile