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)
synchronized List< AbstractFile > findFilesExactName(long parentId, String name)
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)
synchronized static Logger getLogger(String name)
static Case getCurrentCaseThrows()
final AbstractFile dbAbstractFile
final AbstractFile dbAbstractFile