Sleuth Kit Java Bindings (JNI)  4.9.0
Java bindings for using The Sleuth Kit
SleuthkitCase.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2011-2019 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.datamodel;
20 
21 import com.google.common.collect.ImmutableSet;
22 import com.google.common.eventbus.EventBus;
23 import com.mchange.v2.c3p0.ComboPooledDataSource;
24 import com.mchange.v2.c3p0.DataSources;
25 import com.mchange.v2.c3p0.PooledDataSource;
26 import com.zaxxer.sparsebits.SparseBitSet;
27 import java.beans.PropertyVetoException;
28 import java.io.BufferedInputStream;
29 import java.io.BufferedOutputStream;
30 import java.io.File;
31 import java.io.FileInputStream;
32 import java.io.FileOutputStream;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.io.UnsupportedEncodingException;
37 import java.net.InetAddress;
38 import java.net.URLEncoder;
39 import java.nio.charset.StandardCharsets;
40 import java.nio.file.Paths;
41 import java.sql.Connection;
42 import java.sql.DriverManager;
43 import java.sql.PreparedStatement;
44 import java.sql.ResultSet;
45 import java.sql.SQLException;
46 import java.sql.Statement;
47 import java.text.SimpleDateFormat;
48 import java.util.ArrayList;
49 import java.util.Arrays;
50 import java.util.Collection;
51 import java.util.Collections;
52 import java.util.Date;
53 import java.util.EnumMap;
54 import java.util.HashMap;
55 import java.util.HashSet;
56 import java.util.LinkedHashMap;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.MissingResourceException;
60 import java.util.ResourceBundle;
61 import java.util.Set;
62 import java.util.UUID;
63 import java.util.concurrent.ConcurrentHashMap;
64 import java.util.concurrent.locks.ReentrantReadWriteLock;
65 import java.util.logging.Level;
66 import java.util.logging.Logger;
67 import org.postgresql.util.PSQLState;
83 import org.sqlite.SQLiteConfig;
84 import org.sqlite.SQLiteDataSource;
85 import org.sqlite.SQLiteJDBCLoader;
86 
91 public class SleuthkitCase {
92 
93  private static final int MAX_DB_NAME_LEN_BEFORE_TIMESTAMP = 47;
94 
99  static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
100  = new CaseDbSchemaVersionNumber(8, 5);
101 
102  private static final long BASE_ARTIFACT_ID = Long.MIN_VALUE; // Artifact ids will start at the lowest negative value
103  private static final Logger logger = Logger.getLogger(SleuthkitCase.class.getName());
104  private static final ResourceBundle bundle = ResourceBundle.getBundle("org.sleuthkit.datamodel.Bundle");
105  private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
106  private static final String SQL_ERROR_CONNECTION_GROUP = "08";
107  private static final String SQL_ERROR_AUTHENTICATION_GROUP = "28";
108  private static final String SQL_ERROR_PRIVILEGE_GROUP = "42";
109  private static final String SQL_ERROR_RESOURCE_GROUP = "53";
110  private static final String SQL_ERROR_LIMIT_GROUP = "54";
111  private static final String SQL_ERROR_INTERNAL_GROUP = "xx";
112  private static final int MIN_USER_DEFINED_TYPE_ID = 10000;
113 
114  private static final Set<String> CORE_TABLE_NAMES = ImmutableSet.of(
115  "tsk_events",
116  "tsk_event_descriptions",
117  "tsk_event_types",
118  "tsk_db_info",
119  "tsk_objects",
120  "tsk_image_info",
121  "tsk_image_names",
122  "tsk_vs_info",
123  "tsk_vs_parts",
124  "tsk_fs_info",
125  "tsk_file_layout",
126  "tsk_files",
127  "tsk_files_path",
128  "tsk_files_derived",
129  "tsk_files_derived_method",
130  "tag_names",
131  "content_tags",
132  "blackboard_artifact_tags",
133  "blackboard_artifacts",
134  "blackboard_attributes",
135  "blackboard_artifact_types",
136  "blackboard_attribute_types",
137  "data_source_info",
138  "file_encoding_types",
139  "ingest_module_types",
140  "ingest_job_status_types",
141  "ingest_modules",
142  "ingest_jobs",
143  "ingest_job_modules",
144  "account_types",
145  "accounts",
146  "account_relationships",
147  "review_statuses",
148  "reports,");
149 
150  private static final Set<String> CORE_INDEX_NAMES = ImmutableSet.of(
151  "parObjId",
152  "layout_objID",
153  "artifact_objID",
154  "artifact_artifact_objID",
155  "artifact_typeID",
156  "attrsArtifactID",
157  "mime_type",
158  "file_extension",
159  "relationships_account1",
160  "relationships_account2",
161  "relationships_relationship_source_obj_id",
162  "relationships_date_time",
163  "relationships_relationship_type",
164  "relationships_data_source_obj_id",
165  "events_time",
166  "events_type",
167  "events_data_source_obj_id",
168  "events_file_obj_id",
169  "events_artifact_id");
170 
171  private static final String TSK_VERSION_KEY = "TSK_VER";
172  private static final String SCHEMA_MAJOR_VERSION_KEY = "SCHEMA_MAJOR_VERSION";
173  private static final String SCHEMA_MINOR_VERSION_KEY = "SCHEMA_MINOR_VERSION";
174  private static final String CREATION_SCHEMA_MAJOR_VERSION_KEY = "CREATION_SCHEMA_MAJOR_VERSION";
175  private static final String CREATION_SCHEMA_MINOR_VERSION_KEY = "CREATION_SCHEMA_MINOR_VERSION";
176 
177  private final ConnectionPool connections;
178  private final Map<Long, VirtualDirectory> rootIdsToCarvedFileDirs = new HashMap<>();
179  private final Map<Long, FileSystem> fileSystemIdMap = new HashMap<>(); // Cache for file system files.
180  private final List<ErrorObserver> sleuthkitCaseErrorObservers = new ArrayList<>();
181  private final String databaseName;
182  private final String dbPath;
183  private final DbType dbType;
184  private final String caseDirPath;
185  private SleuthkitJNI.CaseDbHandle caseHandle;
186  private String dbBackupPath;
187  private Map<Integer, BlackboardArtifact.Type> typeIdToArtifactTypeMap;
188  private Map<Integer, BlackboardAttribute.Type> typeIdToAttributeTypeMap;
189  private Map<String, BlackboardArtifact.Type> typeNameToArtifactTypeMap;
190  private Map<String, BlackboardAttribute.Type> typeNameToAttributeTypeMap;
191  private CaseDbSchemaVersionNumber caseDBSchemaCreationVersion;
192 
193  /*
194  * First parameter is used to specify the SparseBitSet to use, as object IDs
195  * can be larger than the max size of a SparseBitSet
196  */
197  private final Map<Long, SparseBitSet> hasChildrenBitSetMap = new HashMap<>();
198 
199  private long nextArtifactId; // Used to ensure artifact ids come from the desired range.
200  // This read/write lock is used to implement a layer of locking on top of
201  // the locking protocol provided by the underlying SQLite database. The Java
202  // locking protocol improves performance for reasons that are not currently
203  // understood. Note that the lock is contructed to use a fairness policy.
204  private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
205 
206  private CommunicationsManager communicationsMgr;
207  private TimelineManager timelineMgr;
208  private Blackboard blackboard;
209  private CaseDbAccessManager dbAccessManager;
210  private TaggingManager taggingMgr;
211 
212  private final Map<String, Set<Long>> deviceIdToDatasourceObjIdMap = new HashMap<>();
213 
214  private final EventBus eventBus = new EventBus("SleuthkitCase-EventBus");
215 
216  public void registerForEvents(Object listener) {
217  eventBus.register(listener);
218  }
219 
220  public void unregisterForEvents(Object listener) {
221  eventBus.unregister(listener);
222  }
223 
224  void fireTSKEvent(Object event) {
225  eventBus.post(event);
226  }
227 
228  // Cache of frequently used content objects (e.g. data source, file system).
229  private final Map<Long, Content> frequentlyUsedContentMap = new HashMap<>();
230 
231  private Examiner cachedCurrentExaminer = null;
232 
247  public static void tryConnect(CaseDbConnectionInfo info) throws TskCoreException {
248  // Check if we can talk to the database.
249  if (info.getHost() == null || info.getHost().isEmpty()) {
250  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingHostname")); //NON-NLS
251  } else if (info.getPort() == null || info.getPort().isEmpty()) {
252  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingPort")); //NON-NLS
253  } else if (info.getUserName() == null || info.getUserName().isEmpty()) {
254  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingUsername")); //NON-NLS
255  } else if (info.getPassword() == null || info.getPassword().isEmpty()) {
256  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingPassword")); //NON-NLS
257  }
258 
259  try {
260  Class.forName("org.postgresql.Driver"); //NON-NLS
261  Connection conn = DriverManager.getConnection("jdbc:postgresql://" + info.getHost() + ":" + info.getPort() + "/postgres", info.getUserName(), info.getPassword()); //NON-NLS
262  if (conn != null) {
263  conn.close();
264  }
265  } catch (SQLException ex) {
266  String result;
267  String sqlState = ex.getSQLState().toLowerCase();
268  if (sqlState.startsWith(SQL_ERROR_CONNECTION_GROUP)) {
269  try {
270  if (InetAddress.getByName(info.getHost()).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
271  // if we can reach the host, then it's probably port problem
272  result = bundle.getString("DatabaseConnectionCheck.Port"); //NON-NLS
273  } else {
274  result = bundle.getString("DatabaseConnectionCheck.HostnameOrPort"); //NON-NLS
275  }
276  } catch (IOException | MissingResourceException any) {
277  // it may be anything
278  result = bundle.getString("DatabaseConnectionCheck.Everything"); //NON-NLS
279  }
280  } else if (sqlState.startsWith(SQL_ERROR_AUTHENTICATION_GROUP)) {
281  result = bundle.getString("DatabaseConnectionCheck.Authentication"); //NON-NLS
282  } else if (sqlState.startsWith(SQL_ERROR_PRIVILEGE_GROUP)) {
283  result = bundle.getString("DatabaseConnectionCheck.Access"); //NON-NLS
284  } else if (sqlState.startsWith(SQL_ERROR_RESOURCE_GROUP)) {
285  result = bundle.getString("DatabaseConnectionCheck.ServerDiskSpace"); //NON-NLS
286  } else if (sqlState.startsWith(SQL_ERROR_LIMIT_GROUP)) {
287  result = bundle.getString("DatabaseConnectionCheck.ServerRestart"); //NON-NLS
288  } else if (sqlState.startsWith(SQL_ERROR_INTERNAL_GROUP)) {
289  result = bundle.getString("DatabaseConnectionCheck.InternalServerIssue"); //NON-NLS
290  } else {
291  result = bundle.getString("DatabaseConnectionCheck.Connection"); //NON-NLS
292  }
293  throw new TskCoreException(result);
294  } catch (ClassNotFoundException ex) {
295  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.Installation")); //NON-NLS
296  }
297  }
298 
310  private SleuthkitCase(String dbPath, SleuthkitJNI.CaseDbHandle caseHandle, DbType dbType) throws Exception {
311  Class.forName("org.sqlite.JDBC");
312  this.dbPath = dbPath;
313  this.dbType = dbType;
314  File dbFile = new File(dbPath);
315  this.caseDirPath = dbFile.getParentFile().getAbsolutePath();
316  this.databaseName = dbFile.getName();
317  this.connections = new SQLiteConnections(dbPath);
318  this.caseHandle = caseHandle;
319  init();
320  logSQLiteJDBCDriverInfo();
321  }
322 
340  private SleuthkitCase(String host, int port, String dbName, String userName, String password, SleuthkitJNI.CaseDbHandle caseHandle, String caseDirPath, DbType dbType) throws Exception {
341  this.dbPath = "";
342  this.databaseName = dbName;
343  this.dbType = dbType;
344  this.caseDirPath = caseDirPath;
345  this.connections = new PostgreSQLConnections(host, port, dbName, userName, password);
346  this.caseHandle = caseHandle;
347  init();
348  }
349 
350  private void init() throws Exception {
351  typeIdToArtifactTypeMap = new ConcurrentHashMap<>();
352  typeIdToAttributeTypeMap = new ConcurrentHashMap<>();
353  typeNameToArtifactTypeMap = new ConcurrentHashMap<>();
354  typeNameToAttributeTypeMap = new ConcurrentHashMap<>();
355 
356  /*
357  * The following methods need to be called before updateDatabaseSchema
358  * due to the way that updateFromSchema2toSchema3 was implemented.
359  */
360  initBlackboardArtifactTypes();
361  initBlackboardAttributeTypes();
362  initNextArtifactId();
363  updateDatabaseSchema(null);
364 
365  try (CaseDbConnection connection = connections.getConnection()) {
366  initIngestModuleTypes(connection);
367  initIngestStatusTypes(connection);
368  initReviewStatuses(connection);
369  initEncodingTypes(connection);
370  populateHasChildrenMap(connection);
371  updateExaminers(connection);
372  initDBSchemaCreationVersion(connection);
373  }
374 
375  blackboard = new Blackboard(this);
376  communicationsMgr = new CommunicationsManager(this);
377  timelineMgr = new TimelineManager(this);
378  dbAccessManager = new CaseDbAccessManager(this);
379  taggingMgr = new TaggingManager(this);
380  }
381 
387  static Set<String> getCoreTableNames() {
388  return CORE_TABLE_NAMES;
389  }
390 
396  static Set<String> getCoreIndexNames() {
397  return CORE_INDEX_NAMES;
398  }
399 
408  boolean getHasChildren(Content content) {
409  long objId = content.getId();
410  long mapIndex = objId / Integer.MAX_VALUE;
411  int mapValue = (int) (objId % Integer.MAX_VALUE);
412 
413  synchronized (hasChildrenBitSetMap) {
414  if (hasChildrenBitSetMap.containsKey(mapIndex)) {
415  return hasChildrenBitSetMap.get(mapIndex).get(mapValue);
416  }
417  return false;
418  }
419  }
420 
426  private void setHasChildren(Long objId) {
427  long mapIndex = objId / Integer.MAX_VALUE;
428  int mapValue = (int) (objId % Integer.MAX_VALUE);
429 
430  synchronized (hasChildrenBitSetMap) {
431  if (hasChildrenBitSetMap.containsKey(mapIndex)) {
432  hasChildrenBitSetMap.get(mapIndex).set(mapValue);
433  } else {
434  SparseBitSet bitSet = new SparseBitSet();
435  bitSet.set(mapValue);
436  hasChildrenBitSetMap.put(mapIndex, bitSet);
437  }
438  }
439  }
440 
449  return communicationsMgr;
450  }
451 
458  return blackboard;
459  }
460 
469  return timelineMgr;
470  }
471 
472  /*
473  * Gets the case database access manager for this case.
474  *
475  * @return The per case CaseDbAccessManager object.
476  *
477  * @throws org.sleuthkit.datamodel.TskCoreException
478  */
480  return dbAccessManager;
481  }
482 
488  public synchronized TaggingManager getTaggingManager() {
489  return taggingMgr;
490  }
491 
498  private void initBlackboardArtifactTypes() throws SQLException, TskCoreException {
499  CaseDbConnection connection = connections.getConnection();
500  Statement statement = null;
501  ResultSet resultSet = null;
503  try {
504  statement = connection.createStatement();
505  for (ARTIFACT_TYPE type : ARTIFACT_TYPE.values()) {
506  try {
507  statement.execute("INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name) VALUES (" + type.getTypeID() + " , '" + type.getLabel() + "', '" + type.getDisplayName() + "')"); //NON-NLS
508  } catch (SQLException ex) {
509  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM blackboard_artifact_types WHERE artifact_type_id = '" + type.getTypeID() + "'"); //NON-NLS
510  resultSet.next();
511  if (resultSet.getLong("count") == 0) {
512  throw ex;
513  }
514  resultSet.close();
515  resultSet = null;
516  }
517  this.typeIdToArtifactTypeMap.put(type.getTypeID(), new BlackboardArtifact.Type(type));
518  this.typeNameToArtifactTypeMap.put(type.getLabel(), new BlackboardArtifact.Type(type));
519  }
520  if (dbType == DbType.POSTGRESQL) {
521  int newPrimaryKeyIndex = Collections.max(Arrays.asList(ARTIFACT_TYPE.values())).getTypeID() + 1;
522  statement.execute("ALTER SEQUENCE blackboard_artifact_types_artifact_type_id_seq RESTART WITH " + newPrimaryKeyIndex); //NON-NLS
523  }
524  } finally {
525  closeResultSet(resultSet);
526  closeStatement(statement);
527  connection.close();
529  }
530  }
531 
539  private void initBlackboardAttributeTypes() throws SQLException, TskCoreException {
540  CaseDbConnection connection = connections.getConnection();
541  Statement statement = null;
542  ResultSet resultSet = null;
544  try {
545  statement = connection.createStatement();
546  for (ATTRIBUTE_TYPE type : ATTRIBUTE_TYPE.values()) {
547  try {
548  statement.execute("INSERT INTO blackboard_attribute_types (attribute_type_id, type_name, display_name, value_type) VALUES (" + type.getTypeID() + ", '" + type.getLabel() + "', '" + type.getDisplayName() + "', '" + type.getValueType().getType() + "')"); //NON-NLS
549  } catch (SQLException ex) {
550  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM blackboard_attribute_types WHERE attribute_type_id = '" + type.getTypeID() + "'"); //NON-NLS
551  resultSet.next();
552  if (resultSet.getLong("count") == 0) {
553  throw ex;
554  }
555  resultSet.close();
556  resultSet = null;
557  }
558  this.typeIdToAttributeTypeMap.put(type.getTypeID(), new BlackboardAttribute.Type(type));
559  this.typeNameToAttributeTypeMap.put(type.getLabel(), new BlackboardAttribute.Type(type));
560  }
561  if (this.dbType == DbType.POSTGRESQL) {
562  int newPrimaryKeyIndex = Collections.max(Arrays.asList(ATTRIBUTE_TYPE.values())).getTypeID() + 1;
563  statement.execute("ALTER SEQUENCE blackboard_attribute_types_attribute_type_id_seq RESTART WITH " + newPrimaryKeyIndex); //NON-NLS
564  }
565  } finally {
566  closeResultSet(resultSet);
567  closeStatement(statement);
568  connection.close();
570  }
571  }
572 
582  private void initNextArtifactId() throws SQLException, TskCoreException {
583  CaseDbConnection connection = connections.getConnection();
584  Statement statement = null;
585  ResultSet resultSet = null;
587  try {
588  statement = connection.createStatement();
589  resultSet = connection.executeQuery(statement, "SELECT MAX(artifact_id) AS max_artifact_id FROM blackboard_artifacts"); //NON-NLS
590  resultSet.next();
591  this.nextArtifactId = resultSet.getLong("max_artifact_id") + 1;
592  if (this.nextArtifactId == 1) {
593  this.nextArtifactId = BASE_ARTIFACT_ID;
594  }
595  } finally {
596  closeResultSet(resultSet);
597  closeStatement(statement);
598  connection.close();
600  }
601  }
602 
610  private void initIngestModuleTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
611  Statement statement = null;
612  ResultSet resultSet = null;
614  try {
615  statement = connection.createStatement();
616  for (IngestModuleType type : IngestModuleType.values()) {
617  try {
618  statement.execute("INSERT INTO ingest_module_types (type_id, type_name) VALUES (" + type.ordinal() + ", '" + type.toString() + "');"); //NON-NLS
619  } catch (SQLException ex) {
620  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM ingest_module_types WHERE type_id = " + type.ordinal() + ";"); //NON-NLS
621  resultSet.next();
622  if (resultSet.getLong("count") == 0) {
623  throw ex;
624  }
625  resultSet.close();
626  resultSet = null;
627  }
628  }
629  } finally {
630  closeResultSet(resultSet);
631  closeStatement(statement);
633  }
634  }
635 
643  private void initIngestStatusTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
644  Statement statement = null;
645  ResultSet resultSet = null;
647  try {
648  statement = connection.createStatement();
649  for (IngestJobStatusType type : IngestJobStatusType.values()) {
650  try {
651  statement.execute("INSERT INTO ingest_job_status_types (type_id, type_name) VALUES (" + type.ordinal() + ", '" + type.toString() + "');"); //NON-NLS
652  } catch (SQLException ex) {
653  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM ingest_job_status_types WHERE type_id = " + type.ordinal() + ";"); //NON-NLS
654  resultSet.next();
655  if (resultSet.getLong("count") == 0) {
656  throw ex;
657  }
658  resultSet.close();
659  resultSet = null;
660  }
661  }
662  } finally {
663  closeResultSet(resultSet);
664  closeStatement(statement);
666  }
667  }
668 
675  private void initReviewStatuses(CaseDbConnection connection) throws SQLException, TskCoreException {
676  Statement statement = null;
677  ResultSet resultSet = null;
679  try {
680  statement = connection.createStatement();
681  for (BlackboardArtifact.ReviewStatus status : BlackboardArtifact.ReviewStatus.values()) {
682  try {
683  statement.execute("INSERT INTO review_statuses (review_status_id, review_status_name, display_name) " //NON-NLS
684  + "VALUES (" + status.getID() + ",'" + status.getName() + "','" + status.getDisplayName() + "')"); //NON-NLS
685  } catch (SQLException ex) {
686  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM review_statuses WHERE review_status_id = " + status.getID()); //NON-NLS
687  resultSet.next();
688  if (resultSet.getLong("count") == 0) {
689  throw ex;
690  }
691  resultSet.close();
692  resultSet = null;
693  }
694  }
695  } finally {
696  closeResultSet(resultSet);
697  closeStatement(statement);
699  }
700  }
701 
709  private void initEncodingTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
710  Statement statement = null;
711  ResultSet resultSet = null;
713  try {
714  statement = connection.createStatement();
715  for (TskData.EncodingType type : TskData.EncodingType.values()) {
716  try {
717  statement.execute("INSERT INTO file_encoding_types (encoding_type, name) VALUES (" + type.getType() + " , '" + type.name() + "')"); //NON-NLS
718  } catch (SQLException ex) {
719  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM file_encoding_types WHERE encoding_type = " + type.getType()); //NON-NLS
720  resultSet.next();
721  if (resultSet.getLong("count") == 0) {
722  throw ex;
723  }
724  resultSet.close();
725  resultSet = null;
726  }
727  }
728  } finally {
729  closeResultSet(resultSet);
730  closeStatement(statement);
732  }
733  }
734 
743  private void updateExaminers(CaseDbConnection connection) throws SQLException, TskCoreException {
744 
745  String loginName = System.getProperty("user.name");
746  if (loginName.isEmpty()) {
747  logger.log(Level.SEVERE, "Cannot determine logged in user name");
748  return;
749  }
750 
752  try {
753  PreparedStatement statement;
754  switch (getDatabaseType()) {
755  case POSTGRESQL:
756  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_EXAMINER_POSTGRESQL);
757  break;
758  case SQLITE:
759  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_EXAMINER_SQLITE);
760  break;
761  default:
762  throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
763  }
764  statement.clearParameters();
765  statement.setString(1, loginName);
766  connection.executeUpdate(statement);
767  } catch (SQLException ex) {
768  throw new TskCoreException("Error inserting row in tsk_examiners. login name: " + loginName, ex);
769  } finally {
771  }
772  }
773 
781  private void populateHasChildrenMap(CaseDbConnection connection) throws TskCoreException {
782  long timestamp = System.currentTimeMillis();
783 
784  Statement statement = null;
785  ResultSet resultSet = null;
787  try {
788  statement = connection.createStatement();
789  resultSet = statement.executeQuery("select distinct par_obj_id from tsk_objects"); //NON-NLS
790 
791  synchronized (hasChildrenBitSetMap) {
792  while (resultSet.next()) {
793  setHasChildren(resultSet.getLong("par_obj_id"));
794  }
795  }
796  long delay = System.currentTimeMillis() - timestamp;
797  logger.log(Level.INFO, "Time to initialize parent node cache: {0} ms", delay); //NON-NLS
798  } catch (SQLException ex) {
799  throw new TskCoreException("Error populating parent node cache", ex);
800  } finally {
801  closeResultSet(resultSet);
802  closeStatement(statement);
804  }
805  }
806 
813  void addDataSourceToHasChildrenMap() throws TskCoreException {
814 
815  CaseDbConnection connection = connections.getConnection();
816  try {
817  populateHasChildrenMap(connection);
818  } finally {
819  if (connection != null) {
820  connection.close();
821  }
822  }
823  }
824 
834  private void updateDatabaseSchema(String dbPath) throws Exception {
835  CaseDbConnection connection = connections.getConnection();
836  ResultSet resultSet = null;
837  Statement statement = null;
839  try {
840  connection.beginTransaction();
841 
842  boolean hasMinorVersion = false;
843  ResultSet columns = connection.getConnection().getMetaData().getColumns(null, null, "tsk_db_info", "schema%");
844  while (columns.next()) {
845  if (columns.getString("COLUMN_NAME").equals("schema_minor_ver")) {
846  hasMinorVersion = true;
847  }
848  }
849 
850  // Get the schema version number of the case database from the tsk_db_info table.
851  int dbSchemaMajorVersion;
852  int dbSchemaMinorVersion = 0; //schemas before 7 have no minor version , default it to zero.
853 
854  statement = connection.createStatement();
855  resultSet = connection.executeQuery(statement, "SELECT schema_ver"
856  + (hasMinorVersion ? ", schema_minor_ver" : "")
857  + " FROM tsk_db_info"); //NON-NLS
858  if (resultSet.next()) {
859  dbSchemaMajorVersion = resultSet.getInt("schema_ver"); //NON-NLS
860  if (hasMinorVersion) {
861  //if there is a minor version column, use it, else default to zero.
862  dbSchemaMinorVersion = resultSet.getInt("schema_minor_ver"); //NON-NLS
863  }
864  } else {
865  throw new TskCoreException();
866  }
867  CaseDbSchemaVersionNumber dbSchemaVersion = new CaseDbSchemaVersionNumber(dbSchemaMajorVersion, dbSchemaMinorVersion);
868 
869  resultSet.close();
870  resultSet = null;
871  statement.close();
872  statement = null;
873  //check schema compatibility
874  if (false == CURRENT_DB_SCHEMA_VERSION.isCompatible(dbSchemaVersion)) {
875  //we cannot open a db with a major schema version higher than the current one.
876  throw new TskUnsupportedSchemaVersionException(
877  "Unsupported DB schema version " + dbSchemaVersion + ", the highest supported schema version is " + CURRENT_DB_SCHEMA_VERSION.getMajor() + ".X");
878  } else if (dbSchemaVersion.compareTo(CURRENT_DB_SCHEMA_VERSION) < 0) {
879  //The schema version is compatible,possibly after upgrades.
880 
881  if (null != dbPath) {
882  // Make a backup copy of the database. Client code can get the path of the backup
883  // using the getBackupDatabasePath() method.
884  String backupFilePath = dbPath + ".schemaVer" + dbSchemaVersion.toString() + ".backup"; //NON-NLS
885  copyCaseDB(backupFilePath);
886  dbBackupPath = backupFilePath;
887  }
888 
889  // ***CALL SCHEMA UPDATE METHODS HERE***
890  // Each method should examine the schema version passed to it and either:
891  // a. do nothing and return the schema version unchanged, or
892  // b. upgrade the database and return the schema version that the db was upgraded to.
893  dbSchemaVersion = updateFromSchema2toSchema3(dbSchemaVersion, connection);
894  dbSchemaVersion = updateFromSchema3toSchema4(dbSchemaVersion, connection);
895  dbSchemaVersion = updateFromSchema4toSchema5(dbSchemaVersion, connection);
896  dbSchemaVersion = updateFromSchema5toSchema6(dbSchemaVersion, connection);
897  dbSchemaVersion = updateFromSchema6toSchema7(dbSchemaVersion, connection);
898  dbSchemaVersion = updateFromSchema7toSchema7dot1(dbSchemaVersion, connection);
899  dbSchemaVersion = updateFromSchema7dot1toSchema7dot2(dbSchemaVersion, connection);
900  dbSchemaVersion = updateFromSchema7dot2toSchema8dot0(dbSchemaVersion, connection);
901  dbSchemaVersion = updateFromSchema8dot0toSchema8dot1(dbSchemaVersion, connection);
902  dbSchemaVersion = updateFromSchema8dot1toSchema8dot2(dbSchemaVersion, connection);
903  dbSchemaVersion = updateFromSchema8dot2toSchema8dot3(dbSchemaVersion, connection);
904  dbSchemaVersion = updateFromSchema8dot3toSchema8dot4(dbSchemaVersion, connection);
905  dbSchemaVersion = updateFromSchema8dot4toSchema8dot5(dbSchemaVersion, connection);
906  statement = connection.createStatement();
907  connection.executeUpdate(statement, "UPDATE tsk_db_info SET schema_ver = " + dbSchemaVersion.getMajor() + ", schema_minor_ver = " + dbSchemaVersion.getMinor()); //NON-NLS
908  connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value = " + dbSchemaVersion.getMajor() + " WHERE name = '" + SCHEMA_MAJOR_VERSION_KEY + "'"); //NON-NLS
909  connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value = " + dbSchemaVersion.getMinor() + " WHERE name = '" + SCHEMA_MINOR_VERSION_KEY + "'"); //NON-NLS
910  statement.close();
911  statement = null;
912  }
913 
914  connection.commitTransaction();
915  } catch (Exception ex) { // Cannot do exception multi-catch in Java 6, so use catch-all.
916  connection.rollbackTransaction();
917  throw ex;
918  } finally {
919  closeResultSet(resultSet);
920  closeStatement(statement);
921  connection.close();
923  }
924  }
925 
933  private void initDBSchemaCreationVersion(CaseDbConnection connection) throws SQLException {
934 
935  Statement statement = null;
936  ResultSet resultSet = null;
937  String createdSchemaMajorVersion = "0";
938  String createdSchemaMinorVersion = "0";
940  try {
941  statement = connection.createStatement();
942  resultSet = connection.executeQuery(statement, "SELECT name, value FROM tsk_db_info_extended");
943  while (resultSet.next()) {
944  String name = resultSet.getString("name");
945  if (name.equals(CREATION_SCHEMA_MAJOR_VERSION_KEY) || name.equals("CREATED_SCHEMA_MAJOR_VERSION")) {
946  createdSchemaMajorVersion = resultSet.getString("value");
947  } else if (name.equals(CREATION_SCHEMA_MINOR_VERSION_KEY) || name.equals("CREATED_SCHEMA_MINOR_VERSION")) {
948  createdSchemaMinorVersion = resultSet.getString("value");
949  }
950  }
951 
952  } finally {
953  closeResultSet(resultSet);
954  closeStatement(statement);
956  }
957 
958  caseDBSchemaCreationVersion = new CaseDbSchemaVersionNumber(Integer.parseInt(createdSchemaMajorVersion), Integer.parseInt(createdSchemaMinorVersion));
959  }
960 
970  public void copyCaseDB(String newDBPath) throws IOException {
971  if (dbPath.isEmpty()) {
972  throw new IOException("Copying case database files is not supported for this type of case database"); //NON-NLS
973  }
974  InputStream in = null;
975  OutputStream out = null;
977  try {
978  InputStream inFile = new FileInputStream(dbPath);
979  in = new BufferedInputStream(inFile);
980  OutputStream outFile = new FileOutputStream(newDBPath);
981  out = new BufferedOutputStream(outFile);
982  int bytesRead = in.read();
983  while (bytesRead != -1) {
984  out.write(bytesRead);
985  bytesRead = in.read();
986  }
987  } finally {
988  try {
989  if (in != null) {
990  in.close();
991  }
992  if (out != null) {
993  out.flush();
994  out.close();
995  }
996  } catch (IOException e) {
997  logger.log(Level.WARNING, "Could not close streams after db copy", e); //NON-NLS
998  }
1000  }
1001  }
1002 
1006  private void logSQLiteJDBCDriverInfo() {
1007  try {
1008  SleuthkitCase.logger.info(String.format("sqlite-jdbc version %s loaded in %s mode", //NON-NLS
1009  SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode()
1010  ? "native" : "pure-java")); //NON-NLS
1011  } catch (Exception ex) {
1012  SleuthkitCase.logger.log(Level.SEVERE, "Error querying case database mode", ex);
1013  }
1014  }
1015 
1029  @SuppressWarnings("deprecation")
1030  private CaseDbSchemaVersionNumber updateFromSchema2toSchema3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1031  if (schemaVersion.getMajor() != 2) {
1032  return schemaVersion;
1033  }
1034  Statement statement = null;
1035  Statement updateStatement = null;
1036  ResultSet resultSet = null;
1038  try {
1039  statement = connection.createStatement();
1040 
1041  // Add new tables for tags.
1042  statement.execute("CREATE TABLE tag_names (tag_name_id INTEGER PRIMARY KEY, display_name TEXT UNIQUE, description TEXT NOT NULL, color TEXT NOT NULL)"); //NON-NLS
1043  statement.execute("CREATE TABLE content_tags (tag_id INTEGER PRIMARY KEY, obj_id INTEGER NOT NULL, tag_name_id INTEGER NOT NULL, comment TEXT NOT NULL, begin_byte_offset INTEGER NOT NULL, end_byte_offset INTEGER NOT NULL)"); //NON-NLS
1044  statement.execute("CREATE TABLE blackboard_artifact_tags (tag_id INTEGER PRIMARY KEY, artifact_id INTEGER NOT NULL, tag_name_id INTEGER NOT NULL, comment TEXT NOT NULL)"); //NON-NLS
1045 
1046  // Add a new table for reports.
1047  statement.execute("CREATE TABLE reports (report_id INTEGER PRIMARY KEY, path TEXT NOT NULL, crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL)"); //NON-NLS
1048 
1049  // Add new columns to the image info table.
1050  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN size INTEGER;"); //NON-NLS
1051  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN md5 TEXT;"); //NON-NLS
1052  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN display_name TEXT;"); //NON-NLS
1053 
1054  // Add a new column to the file system info table.
1055  statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN display_name TEXT;"); //NON-NLS
1056 
1057  // Add a new column to the file table.
1058  statement.execute("ALTER TABLE tsk_files ADD COLUMN meta_seq INTEGER;"); //NON-NLS
1059 
1060  // Add new columns and indexes to the attributes table and populate the
1061  // new column. Note that addition of the new column is a denormalization
1062  // to optimize attribute queries.
1063  statement.execute("ALTER TABLE blackboard_attributes ADD COLUMN artifact_type_id INTEGER NULL NOT NULL DEFAULT -1;"); //NON-NLS
1064  statement.execute("CREATE INDEX attribute_artifactTypeId ON blackboard_attributes(artifact_type_id);"); //NON-NLS
1065  statement.execute("CREATE INDEX attribute_valueText ON blackboard_attributes(value_text);"); //NON-NLS
1066  statement.execute("CREATE INDEX attribute_valueInt32 ON blackboard_attributes(value_int32);"); //NON-NLS
1067  statement.execute("CREATE INDEX attribute_valueInt64 ON blackboard_attributes(value_int64);"); //NON-NLS
1068  statement.execute("CREATE INDEX attribute_valueDouble ON blackboard_attributes(value_double);"); //NON-NLS
1069  resultSet = statement.executeQuery("SELECT attrs.artifact_id AS artifact_id, " //NON-NLS
1070  + "arts.artifact_type_id AS artifact_type_id " //NON-NLS
1071  + "FROM blackboard_attributes AS attrs " //NON-NLS
1072  + "INNER JOIN blackboard_artifacts AS arts " //NON-NLS
1073  + "WHERE attrs.artifact_id = arts.artifact_id;"); //NON-NLS
1074  updateStatement = connection.createStatement();
1075  while (resultSet.next()) {
1076  long artifactId = resultSet.getLong("artifact_id");
1077  int artifactTypeId = resultSet.getInt("artifact_type_id");
1078  updateStatement.executeUpdate(
1079  "UPDATE blackboard_attributes " //NON-NLS
1080  + "SET artifact_type_id = " + artifactTypeId //NON-NLS
1081  + " WHERE blackboard_attributes.artifact_id = " + artifactId + ";"); //NON-NLS
1082  }
1083  resultSet.close();
1084  resultSet = null;
1085 
1086  // Convert existing tag artifact and attribute rows to rows in the new tags tables.
1087  // TODO: This code depends on prepared statements that could evolve with
1088  // time, breaking this upgrade. The code that follows should be rewritten
1089  // to do everything with SQL specific to case database schema version 2.
1090  HashMap<String, TagName> tagNames = new HashMap<String, TagName>();
1091  for (BlackboardArtifact artifact : getBlackboardArtifacts(ARTIFACT_TYPE.TSK_TAG_FILE)) {
1092  Content content = getContentById(artifact.getObjectID());
1093  String name = ""; //NON-NLS
1094  String comment = ""; //NON-NLS
1095  ArrayList<BlackboardAttribute> attributes = getBlackboardAttributes(artifact);
1096  for (BlackboardAttribute attribute : attributes) {
1097  if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()) {
1098  name = attribute.getValueString();
1099  } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()) {
1100  comment = attribute.getValueString();
1101  }
1102  }
1103  if (!name.isEmpty()) {
1104  TagName tagName;
1105  if (tagNames.containsKey(name)) {
1106  tagName = tagNames.get(name);
1107  } else {
1108  tagName = addTagName(name, "", TagName.HTML_COLOR.NONE); //NON-NLS
1109  tagNames.put(name, tagName);
1110  }
1111  addContentTag(content, tagName, comment, 0, content.getSize() - 1);
1112  }
1113  }
1114  for (BlackboardArtifact artifact : getBlackboardArtifacts(ARTIFACT_TYPE.TSK_TAG_ARTIFACT)) {
1115  long taggedArtifactId = -1;
1116  String name = ""; //NON-NLS
1117  String comment = ""; //NON-NLS
1118  ArrayList<BlackboardAttribute> attributes = getBlackboardAttributes(artifact);
1119  for (BlackboardAttribute attribute : attributes) {
1120  if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()) {
1121  name = attribute.getValueString();
1122  } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()) {
1123  comment = attribute.getValueString();
1124  } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()) {
1125  taggedArtifactId = attribute.getValueLong();
1126  }
1127  }
1128  if (taggedArtifactId != -1 && !name.isEmpty()) {
1129  TagName tagName;
1130  if (tagNames.containsKey(name)) {
1131  tagName = tagNames.get(name);
1132  } else {
1133  tagName = addTagName(name, "", TagName.HTML_COLOR.NONE); //NON-NLS
1134  tagNames.put(name, tagName);
1135  }
1136  addBlackboardArtifactTag(getBlackboardArtifact(taggedArtifactId), tagName, comment);
1137  }
1138  }
1139  statement.execute(
1140  "DELETE FROM blackboard_attributes WHERE artifact_id IN " //NON-NLS
1141  + "(SELECT artifact_id FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS
1142  + ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1143  + " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ");"); //NON-NLS
1144  statement.execute(
1145  "DELETE FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS
1146  + ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1147  + " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ";"); //NON-NLS
1148 
1149  return new CaseDbSchemaVersionNumber(3, 0);
1150  } finally {
1151  closeStatement(updateStatement);
1152  closeResultSet(resultSet);
1153  closeStatement(statement);
1154  connection.close();
1156  }
1157  }
1158 
1172  private CaseDbSchemaVersionNumber updateFromSchema3toSchema4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1173  if (schemaVersion.getMajor() != 3) {
1174  return schemaVersion;
1175  }
1176 
1177  Statement statement = null;
1178  ResultSet resultSet = null;
1179  Statement queryStatement = null;
1180  ResultSet queryResultSet = null;
1181  Statement updateStatement = null;
1183  try {
1184  // Add mime_type column to tsk_files table. Populate with general
1185  // info artifact file signature data.
1186  statement = connection.createStatement();
1187  updateStatement = connection.createStatement();
1188  statement.execute("ALTER TABLE tsk_files ADD COLUMN mime_type TEXT;");
1189  resultSet = statement.executeQuery("SELECT files.obj_id AS obj_id, attrs.value_text AS value_text "
1190  + "FROM tsk_files AS files, blackboard_attributes AS attrs, blackboard_artifacts AS arts "
1191  + "WHERE files.obj_id = arts.obj_id AND "
1192  + "arts.artifact_id = attrs.artifact_id AND "
1193  + "arts.artifact_type_id = 1 AND "
1194  + "attrs.attribute_type_id = 62");
1195  while (resultSet.next()) {
1196  updateStatement.executeUpdate(
1197  "UPDATE tsk_files " //NON-NLS
1198  + "SET mime_type = '" + resultSet.getString("value_text") + "' " //NON-NLS
1199  + "WHERE tsk_files.obj_id = " + resultSet.getInt("obj_id") + ";"); //NON-NLS
1200  }
1201  resultSet.close();
1202 
1203  // Add value_type column to blackboard_attribute_types table.
1204  statement.execute("ALTER TABLE blackboard_attribute_types ADD COLUMN value_type INTEGER NOT NULL DEFAULT -1;");
1205  resultSet = statement.executeQuery("SELECT * FROM blackboard_attribute_types AS types"); //NON-NLS
1206  while (resultSet.next()) {
1207  int attributeTypeId = resultSet.getInt("attribute_type_id");
1208  String attributeLabel = resultSet.getString("type_name");
1209  if (attributeTypeId < MIN_USER_DEFINED_TYPE_ID) {
1210  updateStatement.executeUpdate(
1211  "UPDATE blackboard_attribute_types " //NON-NLS
1212  + "SET value_type = " + ATTRIBUTE_TYPE.fromLabel(attributeLabel).getValueType().getType() + " " //NON-NLS
1213  + "WHERE blackboard_attribute_types.attribute_type_id = " + attributeTypeId + ";"); //NON-NLS
1214  }
1215  }
1216  resultSet.close();
1217 
1218  // Add a data_sources_info table.
1219  queryStatement = connection.createStatement();
1220  statement.execute("CREATE TABLE data_source_info (obj_id INTEGER PRIMARY KEY, device_id TEXT NOT NULL, time_zone TEXT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id));");
1221  resultSet = statement.executeQuery("SELECT * FROM tsk_objects WHERE par_obj_id IS NULL");
1222  while (resultSet.next()) {
1223  long objectId = resultSet.getLong("obj_id");
1224  String timeZone = "";
1225  queryResultSet = queryStatement.executeQuery("SELECT tzone FROM tsk_image_info WHERE obj_id = " + objectId);
1226  if (queryResultSet.next()) {
1227  timeZone = queryResultSet.getString("tzone");
1228  }
1229  queryResultSet.close();
1230  updateStatement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) "
1231  + "VALUES(" + objectId + ", '" + UUID.randomUUID().toString() + "' , '" + timeZone + "');");
1232  }
1233  resultSet.close();
1234 
1235  // Add data_source_obj_id column to the tsk_files table.
1236  //
1237  // NOTE: A new case database will have the following FK constraint:
1238  //
1239  // REFERENCES data_source_info (obj_id)
1240  //
1241  // The constraint is sacrificed here to avoid having to create and
1242  // populate a new tsk_files table.
1243  //
1244  // TODO: Do this right.
1245  statement.execute("ALTER TABLE tsk_files ADD COLUMN data_source_obj_id BIGINT NOT NULL DEFAULT -1;");
1246  resultSet = statement.executeQuery("SELECT tsk_files.obj_id AS obj_id, par_obj_id FROM tsk_files, tsk_objects WHERE tsk_files.obj_id = tsk_objects.obj_id");
1247  while (resultSet.next()) {
1248  long fileId = resultSet.getLong("obj_id");
1249  long dataSourceId = getDataSourceObjectId(connection, fileId);
1250  updateStatement.executeUpdate("UPDATE tsk_files SET data_source_obj_id = " + dataSourceId + " WHERE obj_id = " + fileId + ";");
1251  }
1252  resultSet.close();
1253  statement.execute("CREATE TABLE ingest_module_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)"); //NON-NLS
1254  statement.execute("CREATE TABLE ingest_job_status_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)"); //NON-NLS
1255  if (this.dbType.equals(DbType.SQLITE)) {
1256  statement.execute("CREATE TABLE ingest_modules (ingest_module_id INTEGER PRIMARY KEY, display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id));"); //NON-NLS
1257  statement.execute("CREATE TABLE ingest_jobs (ingest_job_id INTEGER PRIMARY KEY, obj_id BIGINT NOT NULL, host_name TEXT NOT NULL, start_date_time BIGINT NOT NULL, end_date_time BIGINT NOT NULL, status_id INTEGER NOT NULL, settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id));"); //NON-NLS
1258  } else {
1259  statement.execute("CREATE TABLE ingest_modules (ingest_module_id BIGSERIAL PRIMARY KEY, display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id));"); //NON-NLS
1260  statement.execute("CREATE TABLE ingest_jobs (ingest_job_id BIGSERIAL PRIMARY KEY, obj_id BIGINT NOT NULL, host_name TEXT NOT NULL, start_date_time BIGINT NOT NULL, end_date_time BIGINT NOT NULL, status_id INTEGER NOT NULL, settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id));"); //NON-NLS
1261  }
1262 
1263  statement.execute("CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id), FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id));"); //NON-NLS
1264  initIngestModuleTypes(connection);
1265  initIngestStatusTypes(connection);
1266 
1267  return new CaseDbSchemaVersionNumber(4, 0);
1268 
1269  } finally {
1270  closeResultSet(queryResultSet);
1271  closeStatement(queryStatement);
1272  closeStatement(updateStatement);
1273  closeResultSet(resultSet);
1274  closeStatement(statement);
1276  }
1277  }
1278 
1292  private CaseDbSchemaVersionNumber updateFromSchema4toSchema5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1293  if (schemaVersion.getMajor() != 4) {
1294  return schemaVersion;
1295  }
1296 
1297  Statement statement = null;
1299  try {
1300  // Add the review_statuses lookup table.
1301  statement = connection.createStatement();
1302  statement.execute("CREATE TABLE review_statuses (review_status_id INTEGER PRIMARY KEY, review_status_name TEXT NOT NULL, display_name TEXT NOT NULL)");
1303 
1304  /*
1305  * Add review_status_id column to artifacts table.
1306  *
1307  * NOTE: For DBs created with schema 5 we define a foreign key
1308  * constraint on the review_status_column. We don't bother with this
1309  * for DBs updated to schema 5 because of limitations of the SQLite
1310  * ALTER TABLE command.
1311  */
1312  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN review_status_id INTEGER NOT NULL DEFAULT " + BlackboardArtifact.ReviewStatus.UNDECIDED.getID());
1313 
1314  // Add the encoding table
1315  statement.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL);");
1316  initEncodingTypes(connection);
1317 
1318  /*
1319  * This needs to be done due to a Autopsy/TSK out of synch problem.
1320  * Without this, it is possible to upgrade from version 4 to 5 and
1321  * then 5 to 6, but not from 4 to 6.
1322  */
1323  initReviewStatuses(connection);
1324 
1325  // Add encoding type column to tsk_files_path
1326  // This should really have the FOREIGN KEY constraint but there are problems
1327  // getting that to work, so we don't add it on this upgrade path.
1328  statement.execute("ALTER TABLE tsk_files_path ADD COLUMN encoding_type INTEGER NOT NULL DEFAULT 0;");
1329 
1330  return new CaseDbSchemaVersionNumber(5, 0);
1331 
1332  } finally {
1333  closeStatement(statement);
1335  }
1336  }
1337 
1351  private CaseDbSchemaVersionNumber updateFromSchema5toSchema6(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1352  if (schemaVersion.getMajor() != 5) {
1353  return schemaVersion;
1354  }
1355 
1356  /*
1357  * This upgrade fixes a bug where some releases had artifact review
1358  * status support in the case database and others did not.
1359  */
1360  Statement statement = null;
1361  ResultSet resultSet = null;
1363  try {
1364  /*
1365  * Add the review_statuses lookup table, if missing.
1366  */
1367  statement = connection.createStatement();
1368  statement.execute("CREATE TABLE IF NOT EXISTS review_statuses (review_status_id INTEGER PRIMARY KEY, review_status_name TEXT NOT NULL, display_name TEXT NOT NULL)");
1369 
1370  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM review_statuses"); //NON-NLS
1371  resultSet.next();
1372  if (resultSet.getLong("count") == 0) {
1373  /*
1374  * Add review_status_id column to artifacts table.
1375  *
1376  * NOTE: For DBs created with schema 5 or 6 we define a foreign
1377  * key constraint on the review_status_column. We don't bother
1378  * with this for DBs updated to schema 5 or 6 because of
1379  * limitations of the SQLite ALTER TABLE command.
1380  */
1381  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN review_status_id INTEGER NOT NULL DEFAULT " + BlackboardArtifact.ReviewStatus.UNDECIDED.getID());
1382  }
1383 
1384  return new CaseDbSchemaVersionNumber(6, 0);
1385 
1386  } finally {
1387  closeResultSet(resultSet);
1388  closeStatement(statement);
1390  }
1391  }
1392 
1406  private CaseDbSchemaVersionNumber updateFromSchema6toSchema7(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1407  if (schemaVersion.getMajor() != 6) {
1408  return schemaVersion;
1409  }
1410 
1411  /*
1412  * This upgrade adds an indexed extension column to the tsk_files table.
1413  */
1414  Statement statement = null;
1415  Statement updstatement = null;
1416  ResultSet resultSet = null;
1418  try {
1419  statement = connection.createStatement();
1420  updstatement = connection.createStatement();
1421  statement.execute("ALTER TABLE tsk_files ADD COLUMN extension TEXT");
1422 
1423  resultSet = connection.executeQuery(statement, "SELECT obj_id,name FROM tsk_files"); //NON-NLS
1424  while (resultSet.next()) {
1425  long objID = resultSet.getLong("obj_id");
1426  String name = resultSet.getString("name");
1427  updstatement.executeUpdate("UPDATE tsk_files SET extension = '" + escapeSingleQuotes(extractExtension(name)) + "' "
1428  + "WHERE obj_id = " + objID);
1429  }
1430 
1431  statement.execute("CREATE INDEX file_extension ON tsk_files ( extension )");
1432 
1433  // Add artifact_obj_id column to blackboard_artifacts table, data conversion for old versions isn't necesarry.
1434  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN artifact_obj_id INTEGER NOT NULL DEFAULT -1");
1435 
1436  return new CaseDbSchemaVersionNumber(7, 0);
1437 
1438  } finally {
1439  closeResultSet(resultSet);
1440  closeStatement(statement);
1441  closeStatement(updstatement);
1443  }
1444  }
1445 
1459  private CaseDbSchemaVersionNumber updateFromSchema7toSchema7dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1460  if (schemaVersion.getMajor() != 7) {
1461  return schemaVersion;
1462  }
1463 
1464  if (schemaVersion.getMinor() != 0) {
1465  return schemaVersion;
1466  }
1467 
1468  /*
1469  * This upgrade adds a minor version number column.
1470  */
1471  Statement statement = null;
1472  ResultSet resultSet = null;
1474  try {
1475  statement = connection.createStatement();
1476 
1477  //add the schema minor version number column.
1478  if (schemaVersion.getMinor() == 0) {
1479  //add the schema minor version number column.
1480  statement.execute("ALTER TABLE tsk_db_info ADD COLUMN schema_minor_ver INTEGER DEFAULT 1");
1481  }
1482  return new CaseDbSchemaVersionNumber(7, 1);
1483 
1484  } finally {
1485  closeResultSet(resultSet);
1486  closeStatement(statement);
1488  }
1489  }
1490 
1504  private CaseDbSchemaVersionNumber updateFromSchema7dot1toSchema7dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1505  if (schemaVersion.getMajor() != 7) {
1506  return schemaVersion;
1507  }
1508 
1509  if (schemaVersion.getMinor() != 1) {
1510  return schemaVersion;
1511  }
1512 
1513  Statement statement = null;
1514  Statement updstatement = null;
1515  ResultSet resultSet = null;
1517  try {
1518  //add the data_source_obj_id column to blackboard_artifacts.
1519  statement = connection.createStatement();
1520  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN data_source_obj_id INTEGER NOT NULL DEFAULT -1");
1521 
1522  // populate data_source_obj_id for each artifact
1523  updstatement = connection.createStatement();
1524  resultSet = connection.executeQuery(statement, "SELECT artifact_id, obj_id FROM blackboard_artifacts"); //NON-NLS
1525  while (resultSet.next()) {
1526  long artifact_id = resultSet.getLong("artifact_id");
1527  long obj_id = resultSet.getLong("obj_id");
1528  long data_source_obj_id = getDataSourceObjectId(connection, obj_id);
1529  updstatement.executeUpdate("UPDATE blackboard_artifacts SET data_source_obj_id = " + data_source_obj_id + " "
1530  + "WHERE artifact_id = " + artifact_id);
1531  }
1532  closeResultSet(resultSet);
1533  closeStatement(statement);
1534  closeStatement(updstatement);
1535 
1536  /*
1537  * Add a knownStatus column to the tag_names table.
1538  */
1539  statement = connection.createStatement();
1540  statement.execute("ALTER TABLE tag_names ADD COLUMN knownStatus INTEGER NOT NULL DEFAULT " + TskData.FileKnown.UNKNOWN.getFileKnownValue());
1541 
1542  // Create account_types, accounts, and account_relationships table
1543  if (this.dbType.equals(DbType.SQLITE)) {
1544  statement.execute("CREATE TABLE account_types (account_type_id INTEGER PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
1545  statement.execute("CREATE TABLE accounts (account_id INTEGER PRIMARY KEY, account_type_id INTEGER NOT NULL, account_unique_identifier TEXT NOT NULL, UNIQUE(account_type_id, account_unique_identifier) , FOREIGN KEY(account_type_id) REFERENCES account_types(account_type_id))");
1546  statement.execute("CREATE TABLE account_relationships (relationship_id INTEGER PRIMARY KEY, account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, relationship_source_obj_id INTEGER NOT NULL, date_time INTEGER, relationship_type INTEGER NOT NULL, data_source_obj_id INTEGER NOT NULL, UNIQUE(account1_id, account2_id, relationship_source_obj_id), FOREIGN KEY(account1_id) REFERENCES accounts(account_id), FOREIGN KEY(account2_id) REFERENCES accounts(account_id), FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id))");
1547  } else {
1548  statement.execute("CREATE TABLE account_types (account_type_id BIGSERIAL PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
1549  statement.execute("CREATE TABLE accounts (account_id BIGSERIAL PRIMARY KEY, account_type_id INTEGER NOT NULL, account_unique_identifier TEXT NOT NULL, UNIQUE(account_type_id, account_unique_identifier) , FOREIGN KEY(account_type_id) REFERENCES account_types(account_type_id))");
1550  statement.execute("CREATE TABLE account_relationships (relationship_id BIGSERIAL PRIMARY KEY, account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, relationship_source_obj_id INTEGER NOT NULL, date_time BIGINT, relationship_type INTEGER NOT NULL, data_source_obj_id INTEGER NOT NULL, UNIQUE(account1_id, account2_id, relationship_source_obj_id), FOREIGN KEY(account1_id) REFERENCES accounts(account_id), FOREIGN KEY(account2_id) REFERENCES accounts(account_id), FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id), FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id))");
1551  }
1552 
1553  // Create indexes
1554  statement.execute("CREATE INDEX artifact_artifact_objID ON blackboard_artifacts(artifact_obj_id)");
1555  statement.execute("CREATE INDEX relationships_account1 ON account_relationships(account1_id)");
1556  statement.execute("CREATE INDEX relationships_account2 ON account_relationships(account2_id)");
1557  statement.execute("CREATE INDEX relationships_relationship_source_obj_id ON account_relationships(relationship_source_obj_id)");
1558  statement.execute("CREATE INDEX relationships_date_time ON account_relationships(date_time)");
1559  statement.execute("CREATE INDEX relationships_relationship_type ON account_relationships(relationship_type)");
1560  statement.execute("CREATE INDEX relationships_data_source_obj_id ON account_relationships(data_source_obj_id)");
1561 
1562  return new CaseDbSchemaVersionNumber(7, 2);
1563  } finally {
1564  closeResultSet(resultSet);
1565  closeStatement(statement);
1566  closeStatement(updstatement);
1568  }
1569  }
1570 
1584  private CaseDbSchemaVersionNumber updateFromSchema7dot2toSchema8dot0(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1585  if (schemaVersion.getMajor() != 7) {
1586  return schemaVersion;
1587  }
1588 
1589  if (schemaVersion.getMinor() != 2) {
1590  return schemaVersion;
1591  }
1592 
1593  Statement updateSchemaStatement = connection.createStatement();
1594  Statement getExistingReportsStatement = connection.createStatement();
1595  ResultSet resultSet = null;
1596  ResultSet existingReports = null;
1597 
1599  try {
1600  // Update the schema to turn report_id into an object id.
1601 
1602  // Unfortunately, SQLite doesn't support adding a constraint
1603  // to an existing table so we have to rename the old...
1604  updateSchemaStatement.execute("ALTER TABLE reports RENAME TO old_reports");
1605 
1606  // ...create the new...
1607  updateSchemaStatement.execute("CREATE TABLE reports (obj_id BIGSERIAL PRIMARY KEY, path TEXT NOT NULL, crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id))");
1608 
1609  // ...add the existing report records back...
1610  existingReports = getExistingReportsStatement.executeQuery("SELECT * FROM old_reports");
1611  while (existingReports.next()) {
1612  String path = existingReports.getString(2);
1613  long crtime = existingReports.getInt(3);
1614  String sourceModule = existingReports.getString(4);
1615  String reportName = existingReports.getString(5);
1616 
1617  PreparedStatement insertObjectStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OBJECT, Statement.RETURN_GENERATED_KEYS);
1618  insertObjectStatement.clearParameters();
1619  insertObjectStatement.setNull(1, java.sql.Types.BIGINT);
1620  insertObjectStatement.setLong(2, TskData.ObjectType.REPORT.getObjectType());
1621  connection.executeUpdate(insertObjectStatement);
1622  resultSet = insertObjectStatement.getGeneratedKeys();
1623  if (!resultSet.next()) {
1624  throw new TskCoreException(String.format("Failed to INSERT report %s (%s) in tsk_objects table", reportName, path));
1625  }
1626  long objectId = resultSet.getLong(1); //last_insert_rowid()
1627 
1628  // INSERT INTO reports (obj_id, path, crtime, src_module_name, display_name) VALUES (?, ?, ?, ?, ?)
1629  PreparedStatement insertReportStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_REPORT);
1630  insertReportStatement.clearParameters();
1631  insertReportStatement.setLong(1, objectId);
1632  insertReportStatement.setString(2, path);
1633  insertReportStatement.setLong(3, crtime);
1634  insertReportStatement.setString(4, sourceModule);
1635  insertReportStatement.setString(5, reportName);
1636  connection.executeUpdate(insertReportStatement);
1637  }
1638 
1639  // ...and drop the old table.
1640  updateSchemaStatement.execute("DROP TABLE old_reports");
1641 
1642  return new CaseDbSchemaVersionNumber(8, 0);
1643  } finally {
1644  closeResultSet(resultSet);
1645  closeResultSet(existingReports);
1646  closeStatement(updateSchemaStatement);
1647  closeStatement(getExistingReportsStatement);
1649  }
1650  }
1651 
1665  private CaseDbSchemaVersionNumber updateFromSchema8dot0toSchema8dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1666  if (schemaVersion.getMajor() != 8) {
1667  return schemaVersion;
1668  }
1669 
1670  if (schemaVersion.getMinor() != 0) {
1671  return schemaVersion;
1672  }
1673 
1675 
1676  try (Statement statement = connection.createStatement();) {
1677  // create examiners table
1678  if (this.dbType.equals(DbType.SQLITE)) {
1679  statement.execute("CREATE TABLE tsk_examiners (examiner_id INTEGER PRIMARY KEY, login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name) )");
1680  statement.execute("ALTER TABLE content_tags ADD COLUMN examiner_id INTEGER REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1681  statement.execute("ALTER TABLE blackboard_artifact_tags ADD COLUMN examiner_id INTEGER REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1682  } else {
1683  statement.execute("CREATE TABLE tsk_examiners (examiner_id BIGSERIAL PRIMARY KEY, login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))");
1684  statement.execute("ALTER TABLE content_tags ADD COLUMN examiner_id BIGINT REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1685  statement.execute("ALTER TABLE blackboard_artifact_tags ADD COLUMN examiner_id BIGINT REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1686  }
1687 
1688  return new CaseDbSchemaVersionNumber(8, 1);
1689  } finally {
1691  }
1692  }
1693 
1707  private CaseDbSchemaVersionNumber updateFromSchema8dot1toSchema8dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1708  if (schemaVersion.getMajor() != 8) {
1709  return schemaVersion;
1710  }
1711 
1712  if (schemaVersion.getMinor() != 1) {
1713  return schemaVersion;
1714  }
1715 
1717 
1718  try (Statement statement = connection.createStatement();) {
1719  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN sha1 TEXT DEFAULT NULL");
1720  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN sha256 TEXT DEFAULT NULL");
1721 
1722  statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_details TEXT");
1723 
1724  /*
1725  * Add new tsk_db_extended_info table with TSK version, creation
1726  * time schema and schema version numbers as the initial data. The
1727  * creation time schema version is set to 0, 0 to indicate that it
1728  * is not known.
1729  */
1730  statement.execute("CREATE TABLE tsk_db_info_extended (name TEXT PRIMARY KEY, value TEXT NOT NULL)");
1731  ResultSet result = statement.executeQuery("SELECT tsk_ver FROM tsk_db_info");
1732  result.next();
1733  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + TSK_VERSION_KEY + "', '" + result.getLong("tsk_ver") + "')");
1734  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + SCHEMA_MAJOR_VERSION_KEY + "', '8')");
1735  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + SCHEMA_MINOR_VERSION_KEY + "', '2')");
1736  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '0')");
1737  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + CREATION_SCHEMA_MINOR_VERSION_KEY + "', '0')");
1738 
1739  String primaryKeyType;
1740  switch (getDatabaseType()) {
1741  case POSTGRESQL:
1742  primaryKeyType = "BIGSERIAL";
1743  break;
1744  case SQLITE:
1745  primaryKeyType = "INTEGER";
1746  break;
1747  default:
1748  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1749  }
1750 
1751  //create and initialize tsk_event_types tables
1752  statement.execute("CREATE TABLE tsk_event_types ("
1753  + " event_type_id " + primaryKeyType + " PRIMARY KEY, "
1754  + " display_name TEXT UNIQUE NOT NULL, "
1755  + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
1756  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1757  + " values( 0, 'Event Types', null)");
1758  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1759  + " values(1, 'File System', 0)");
1760  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1761  + " values(2, 'Web Activity', 0)");
1762  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1763  + " values(3, 'Misc Types', 0)");
1764  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1765  + " values(4, 'Modified', 1)");
1766  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1767  + " values(5, 'Accessed', 1)");
1768  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1769  + " values(6, 'Created', 1)");
1770  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1771  + " values(7, 'Changed', 1)");
1772 
1773  //create tsk_events tables
1774  statement.execute("CREATE TABLE tsk_event_descriptions ("
1775  + " event_description_id " + primaryKeyType + " PRIMARY KEY, "
1776  + " full_description TEXT NOT NULL, "
1777  + " med_description TEXT, "
1778  + " short_description TEXT,"
1779  + " data_source_obj_id BIGINT NOT NULL, "
1780  + " file_obj_id BIGINT NOT NULL, "
1781  + " artifact_id BIGINT, "
1782  + " hash_hit INTEGER NOT NULL, " //boolean
1783  + " tagged INTEGER NOT NULL, " //boolean
1784  + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
1785  + " FOREIGN KEY(file_obj_id) REFERENCES tsk_files(obj_id), "
1786  + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
1787  );
1788 
1789  statement.execute("CREATE TABLE tsk_events ( "
1790  + " event_id " + primaryKeyType + " PRIMARY KEY, "
1791  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
1792  + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
1793  + " time INTEGER NOT NULL) "
1794  );
1795 
1796  //create tsk_events indices
1797  statement.execute("CREATE INDEX events_time ON tsk_events(time)");
1798  statement.execute("CREATE INDEX events_type ON tsk_events(event_type_id)");
1799  statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
1800  statement.execute("CREATE INDEX events_file_obj_id ON tsk_event_descriptions(file_obj_id) ");
1801  statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
1802  statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
1803  return new CaseDbSchemaVersionNumber(8, 2);
1804 
1805  } finally {
1807  }
1808  }
1809 
1823  private CaseDbSchemaVersionNumber updateFromSchema8dot2toSchema8dot3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1824  if (schemaVersion.getMajor() != 8) {
1825  return schemaVersion;
1826  }
1827 
1828  if (schemaVersion.getMinor() != 2) {
1829  return schemaVersion;
1830  }
1831 
1833 
1834  ResultSet resultSet = null;
1835 
1836  try (Statement statement = connection.createStatement();) {
1837 
1838  // Add the uniqueness constraint to the tsk_event and tsk_event_description tables.
1839  // Unfortunately, SQLite doesn't support adding a constraint
1840  // to an existing table so we have to rename the old...
1841  String primaryKeyType;
1842  switch (getDatabaseType()) {
1843  case POSTGRESQL:
1844  primaryKeyType = "BIGSERIAL";
1845  break;
1846  case SQLITE:
1847  primaryKeyType = "INTEGER";
1848  break;
1849  default:
1850  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1851  }
1852 
1853  //create and initialize tsk_event_types tables which may or may not exist
1854  statement.execute("CREATE TABLE IF NOT EXISTS tsk_event_types ("
1855  + " event_type_id " + primaryKeyType + " PRIMARY KEY, "
1856  + " display_name TEXT UNIQUE NOT NULL, "
1857  + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
1858 
1859  resultSet = statement.executeQuery("SELECT * from tsk_event_types");
1860 
1861  // If there is something in resultSet then the table must have previously
1862  // existing therefore there is not need to populate
1863  if (!resultSet.next()) {
1864 
1865  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1866  + " values( 0, 'Event Types', null)");
1867  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1868  + " values(1, 'File System', 0)");
1869  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1870  + " values(2, 'Web Activity', 0)");
1871  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1872  + " values(3, 'Misc Types', 0)");
1873  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1874  + " values(4, 'Modified', 1)");
1875  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1876  + " values(5, 'Accessed', 1)");
1877  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1878  + " values(6, 'Created', 1)");
1879  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1880  + " values(7, 'Changed', 1)");
1881  }
1882 
1883  // Delete the old table that may have been created with the upgrade
1884  // from 8.1 to 8.2.
1885  statement.execute("DROP TABLE IF EXISTS tsk_events");
1886 
1887  // Delete the old table that may have been created with the upgrade
1888  // from 8.1 to 8.2
1889  statement.execute("DROP TABLE IF EXISTS tsk_event_descriptions");
1890 
1891  //create new tsk_event_description table
1892  statement.execute("CREATE TABLE tsk_event_descriptions ("
1893  + " event_description_id " + primaryKeyType + " PRIMARY KEY, "
1894  + " full_description TEXT NOT NULL, "
1895  + " med_description TEXT, "
1896  + " short_description TEXT,"
1897  + " data_source_obj_id BIGINT NOT NULL, "
1898  + " file_obj_id BIGINT NOT NULL, "
1899  + " artifact_id BIGINT, "
1900  + " hash_hit INTEGER NOT NULL, " //boolean
1901  + " tagged INTEGER NOT NULL, " //boolean
1902  + " UNIQUE(full_description, file_obj_id, artifact_id), "
1903  + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
1904  + " FOREIGN KEY(file_obj_id) REFERENCES tsk_files(obj_id), "
1905  + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
1906  );
1907 
1908  // create a new table
1909  statement.execute("CREATE TABLE tsk_events ( "
1910  + " event_id " + primaryKeyType + " PRIMARY KEY, "
1911  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
1912  + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
1913  + " time INTEGER NOT NULL, "
1914  + " UNIQUE (event_type_id, event_description_id, time))"
1915  );
1916 
1917  // Fix mistakenly set names in tsk_db_info_extended
1918  statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MAJOR_VERSION' WHERE name = 'CREATED_SCHEMA_MAJOR_VERSION'");
1919  statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MINOR_VERSION' WHERE name = 'CREATED_SCHEMA_MINOR_VERSION'");
1920 
1921  return new CaseDbSchemaVersionNumber(8, 3);
1922  } finally {
1923  closeResultSet(resultSet);
1925  }
1926  }
1927 
1949  private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1950  if (schemaVersion.getMajor() != 8) {
1951  return schemaVersion;
1952  }
1953 
1954  if (schemaVersion.getMinor() != 3) {
1955  return schemaVersion;
1956  }
1957 
1958  Statement statement = connection.createStatement();
1959  ResultSet results = null;
1960 
1962  try {
1963  // This is a bug fix update for a misnamed column in tsk_event_descriptions in
1964  // the previous update code.
1965  if (null == getDatabaseType()) {
1966  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1967  }
1968 
1969  switch (getDatabaseType()) {
1970  case POSTGRESQL:
1971  // Check if the misnamed column is present
1972  results = statement.executeQuery("SELECT column_name FROM information_schema.columns "
1973  + "WHERE table_name='tsk_event_descriptions' and column_name='file_obj_id'");
1974  if (results.next()) {
1975  // In PostgreSQL we can rename the column if it exists
1976  statement.execute("ALTER TABLE tsk_event_descriptions "
1977  + "RENAME COLUMN file_obj_id TO content_obj_id");
1978 
1979  // In 8.2 to 8.3 upgrade, the event_id & time column in tsk_events table was erroneously created as type INTEGER, instead of BIGINT
1980  // Fix the schema, preserving any data if exists.
1981  statement.execute("CREATE TABLE temp_tsk_events ( "
1982  + " event_id BIGSERIAL PRIMARY KEY, "
1983  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
1984  + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id),"
1985  + " time BIGINT NOT NULL, "
1986  + " UNIQUE (event_type_id, event_description_id, time))"
1987  );
1988 
1989  // Copy the data
1990  statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, "
1991  + "event_description_id, time) SELECT * FROM tsk_events");
1992 
1993  // Drop the old table
1994  statement.execute("DROP TABLE tsk_events");
1995 
1996  // Rename the new table
1997  statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events");
1998 
1999  //create tsk_events indices that were skipped in the 8.2 to 8.3 update code
2000  statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2001  statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) ");
2002  statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2003  statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2004  statement.execute("CREATE INDEX events_time ON tsk_events(time) ");
2005  }
2006  break;
2007  case SQLITE:
2008  boolean hasMisnamedColumn = false;
2009  results = statement.executeQuery("pragma table_info('tsk_event_descriptions')");
2010  while (results.next()) {
2011  if (results.getString("name") != null && results.getString("name").equals("file_obj_id")) {
2012  hasMisnamedColumn = true;
2013  break;
2014  }
2015  }
2016 
2017  if (hasMisnamedColumn) {
2018  // Since we can't rename the column we'll need to make new tables and copy the data
2019  statement.execute("CREATE TABLE temp_tsk_event_descriptions ("
2020  + " event_description_id INTEGER PRIMARY KEY, "
2021  + " full_description TEXT NOT NULL, "
2022  + " med_description TEXT, "
2023  + " short_description TEXT,"
2024  + " data_source_obj_id BIGINT NOT NULL, "
2025  + " content_obj_id BIGINT NOT NULL, "
2026  + " artifact_id BIGINT, "
2027  + " hash_hit INTEGER NOT NULL, " //boolean
2028  + " tagged INTEGER NOT NULL, " //boolean
2029  + " UNIQUE(full_description, content_obj_id, artifact_id), "
2030  + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
2031  + " FOREIGN KEY(content_obj_id) REFERENCES tsk_files(obj_id), "
2032  + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
2033  );
2034 
2035  statement.execute("CREATE TABLE temp_tsk_events ( "
2036  + " event_id INTEGER PRIMARY KEY, "
2037  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
2038  + " event_description_id BIGINT NOT NULL REFERENCES temp_tsk_event_descriptions(event_description_id),"
2039  + " time INTEGER NOT NULL, "
2040  + " UNIQUE (event_type_id, event_description_id, time))"
2041  );
2042 
2043  // Copy the data
2044  statement.execute("INSERT INTO temp_tsk_event_descriptions(event_description_id, full_description, "
2045  + "med_description, short_description, data_source_obj_id, content_obj_id, artifact_id, "
2046  + "hash_hit, tagged) SELECT * FROM tsk_event_descriptions");
2047 
2048  statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, "
2049  + "event_description_id, time) SELECT * FROM tsk_events");
2050 
2051  // Drop the old tables
2052  statement.execute("DROP TABLE tsk_events");
2053  statement.execute("DROP TABLE tsk_event_descriptions");
2054 
2055  // Rename the new tables
2056  statement.execute("ALTER TABLE temp_tsk_event_descriptions RENAME TO tsk_event_descriptions");
2057  statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events");
2058 
2059  //create tsk_events indices
2060  statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2061  statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) ");
2062  statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2063  statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2064  statement.execute("CREATE INDEX events_time ON tsk_events(time) ");
2065  }
2066  break;
2067  default:
2068  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
2069  }
2070 
2071  // create pool info table
2072  if (this.dbType.equals(DbType.SQLITE)) {
2073  statement.execute("CREATE TABLE tsk_pool_info (obj_id INTEGER PRIMARY KEY, pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
2074  } else {
2075  statement.execute("CREATE TABLE tsk_pool_info (obj_id BIGSERIAL PRIMARY KEY, pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
2076  }
2077 
2078  // Add new account types for newly supported messaging applications, if they dont exists already.
2079  insertAccountTypeIfNotExists(statement, "IMO", "IMO");
2080  insertAccountTypeIfNotExists(statement, "LINE", "LINE");
2081  insertAccountTypeIfNotExists(statement, "SKYPE", "Skype");
2082  insertAccountTypeIfNotExists(statement, "TANGO", "Tango");
2083  insertAccountTypeIfNotExists(statement, "TEXTNOW", "TextNow");
2084  insertAccountTypeIfNotExists(statement, "THREEMA", "ThreeMa");
2085  insertAccountTypeIfNotExists(statement, "VIBER", "Viber");
2086  insertAccountTypeIfNotExists(statement, "XENDER", "Xender");
2087  insertAccountTypeIfNotExists(statement, "ZAPYA", "Zapya");
2088  insertAccountTypeIfNotExists(statement, "SHAREIT", "ShareIt");
2089 
2090  return new CaseDbSchemaVersionNumber(8, 4);
2091  } finally {
2092  closeResultSet(results);
2093  closeStatement(statement);
2095  }
2096  }
2097 
2098  private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2099  if (schemaVersion.getMajor() != 8) {
2100  return schemaVersion;
2101  }
2102 
2103  if (schemaVersion.getMinor() != 4) {
2104  return schemaVersion;
2105  }
2106 
2107  Statement statement = connection.createStatement();
2109  try {
2110  switch (getDatabaseType()) {
2111  case POSTGRESQL:
2112  statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id BIGSERIAL PRIMARY KEY, name TEXT UNIQUE)");
2113  statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id BIGINT REFERENCES tsk_tag_sets(tag_set_id)");
2114  break;
2115  case SQLITE:
2116  statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id INTEGER PRIMARY KEY, name TEXT UNIQUE)");
2117  statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id INTEGER REFERENCES tsk_tag_sets(tag_set_id)");
2118  break;
2119  }
2120 
2121  statement.execute("ALTER TABLE tag_names ADD COLUMN rank INTEGER");
2122 
2123  String insertStmt = "INSERT INTO tsk_tag_sets (name) VALUES ('Project VIC')";
2124  if (getDatabaseType() == DbType.POSTGRESQL) {
2125  statement.execute(insertStmt, Statement.RETURN_GENERATED_KEYS);
2126  } else {
2127  statement.execute(insertStmt);
2128  }
2129  try (ResultSet resultSet = statement.getGeneratedKeys()) {
2130  if (resultSet != null && resultSet.next()) {
2131  int tagSetId = resultSet.getInt(1);
2132 
2133  String updateQuery = "UPDATE tag_names SET tag_set_id = %d, color = '%s', rank = %d, display_name = '%s' WHERE display_name = '%s'";
2134  statement.executeUpdate(String.format(updateQuery, tagSetId, "Red", 1, "Child Exploitation (Illegal)", "CAT-1: Child Exploitation (Illegal)"));
2135  statement.executeUpdate(String.format(updateQuery, tagSetId, "Lime", 2, "Child Exploitation (Non-Illegal/Age Difficult)", "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)"));
2136  statement.executeUpdate(String.format(updateQuery, tagSetId, "Yellow", 3, "CGI/Animation (Child Exploitive)", "CAT-3: CGI/Animation (Child Exploitive)"));
2137  statement.executeUpdate(String.format(updateQuery, tagSetId, "Purple", 4, "Exemplar/Comparison (Internal Use Only)", "CAT-4: Exemplar/Comparison (Internal Use Only)"));
2138  statement.executeUpdate(String.format(updateQuery, tagSetId, "Fuchsia", 5, "Non-pertinent", "CAT-5: Non-pertinent"));
2139 
2140  String deleteContentTag = "DELETE FROM content_tags WHERE tag_name_id IN (SELECT tag_name_id from tag_names WHERE display_name LIKE 'CAT-0: Uncategorized')";
2141  String deleteArtifactTag = "DELETE FROM blackboard_artifact_tags WHERE tag_name_id IN (SELECT tag_name_id from tag_names WHERE display_name LIKE 'CAT-0: Uncategorized')";
2142  String deleteCat0 = "DELETE FROM tag_names WHERE display_name = 'CAT-0: Uncategorized'";
2143  statement.executeUpdate(deleteContentTag);
2144  statement.executeUpdate(deleteArtifactTag);
2145  statement.executeUpdate(deleteCat0);
2146 
2147  } else {
2148  throw new TskCoreException("Failed to retrieve the default tag_set_id from DB");
2149  }
2150  }
2151 
2152  // Add data_source_obj_id column to the tsk_files table. For newly created cases
2153  // this column will have a foreign key constraint on the data_source_info table.
2154  // There does not seem to be a reasonable way to do this in an upgrade,
2155  // so upgraded cases will be missing the foreign key.
2156  switch (getDatabaseType()) {
2157  case POSTGRESQL:
2158  statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN data_source_obj_id BIGINT NOT NULL DEFAULT -1;");
2159  break;
2160  case SQLITE:
2161  statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN data_source_obj_id INTEGER NOT NULL DEFAULT -1;");
2162  break;
2163  }
2164  Statement updateStatement = connection.createStatement();
2165  try (ResultSet resultSet = statement.executeQuery("SELECT obj_id FROM tsk_fs_info")) {
2166  while (resultSet.next()) {
2167  long fsId = resultSet.getLong("obj_id");
2168  long dataSourceId = getDataSourceObjectId(connection, fsId);
2169  updateStatement.executeUpdate("UPDATE tsk_fs_info SET data_source_obj_id = " + dataSourceId + " WHERE obj_id = " + fsId + ";");
2170  }
2171  } finally {
2172  closeStatement(updateStatement);
2173  }
2174 
2175  return new CaseDbSchemaVersionNumber(8, 5);
2176 
2177  } finally {
2178  closeStatement(statement);
2180  }
2181  }
2182 
2194  private void insertAccountTypeIfNotExists(Statement statement, String type_name, String display_name) throws TskCoreException, SQLException {
2195 
2196  String insertSQL = String.format("INTO account_types(type_name, display_name) VALUES ('%s', '%s')", type_name, display_name);
2197  switch (getDatabaseType()) {
2198  case POSTGRESQL:
2199  insertSQL = "INSERT " + insertSQL + " ON CONFLICT DO NOTHING"; //NON-NLS
2200  break;
2201  case SQLITE:
2202  insertSQL = "INSERT OR IGNORE " + insertSQL;
2203  break;
2204  default:
2205  throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
2206  }
2207  statement.execute(insertSQL); //NON-NLS
2208  }
2209 
2217  static String extractExtension(final String fileName) {
2218  String ext;
2219  int i = fileName.lastIndexOf(".");
2220  // > 0 because we assume it's not an extension if period is the first character
2221  if ((i > 0) && ((i + 1) < fileName.length())) {
2222  ext = fileName.substring(i + 1);
2223  } else {
2224  return "";
2225  }
2226  // we added this at one point to deal with files that had crazy names based on URLs
2227  // it's too hard though to clean those up and not mess up basic extensions though.
2228  // We need to add '-' to the below if we use it again
2229  // String[] findNonAlphanumeric = ext.split("[^a-zA-Z0-9_]");
2230  // if (findNonAlphanumeric.length > 1) {
2231  // ext = findNonAlphanumeric[0];
2232  // }
2233  return ext.toLowerCase();
2234  }
2235 
2246  @Deprecated
2247  public int getSchemaVersion() {
2248  return getDBSchemaVersion().getMajor();
2249  }
2250 
2257  return CURRENT_DB_SCHEMA_VERSION;
2258  }
2259 
2267  return caseDBSchemaCreationVersion;
2268  }
2269 
2276  return this.dbType;
2277  }
2278 
2285  public String getBackupDatabasePath() {
2286  return dbBackupPath;
2287  }
2288 
2303  public CaseDbTransaction beginTransaction() throws TskCoreException {
2304  return new CaseDbTransaction(this, connections.getConnection());
2305  }
2306 
2312  public String getDatabaseName() {
2313  return databaseName;
2314  }
2315 
2322  public String getDbDirPath() {
2323  return caseDirPath;
2324  }
2325 
2332  if (dbType == DbType.SQLITE) {
2333  rwLock.writeLock().lock();
2334  }
2335  }
2336 
2343  if (dbType == DbType.SQLITE) {
2344  rwLock.writeLock().unlock();
2345  }
2346  }
2347 
2354  if (dbType == DbType.SQLITE) {
2355  rwLock.readLock().lock();
2356  }
2357  }
2358 
2365  if (dbType == DbType.SQLITE) {
2366  rwLock.readLock().unlock();
2367  }
2368  }
2369 
2379  public static SleuthkitCase openCase(String dbPath) throws TskCoreException {
2380  try {
2381  final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath);
2382  return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE);
2384  //don't wrap in new TskCoreException
2385  throw ex;
2386  } catch (Exception ex) {
2387  throw new TskCoreException("Failed to open case database at " + dbPath, ex);
2388  }
2389  }
2390 
2402  public static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir) throws TskCoreException {
2403  try {
2404  /*
2405  * The flow of this method involves trying to open case and if
2406  * successful, return that case. If unsuccessful, an exception is
2407  * thrown. We catch any exceptions, and use tryConnect() to attempt
2408  * to obtain further information about the error. If tryConnect() is
2409  * unable to successfully connect, tryConnect() will throw a
2410  * TskCoreException with a message containing user-level error
2411  * reporting. If tryConnect() is able to connect, flow continues and
2412  * we rethrow the original exception obtained from trying to create
2413  * the case. In this way, we obtain more detailed information if we
2414  * are able, but do not lose any information if unable.
2415  */
2416  final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info);
2417  return new SleuthkitCase(info.getHost(), Integer.parseInt(info.getPort()), databaseName, info.getUserName(), info.getPassword(), caseHandle, caseDir, info.getDbType());
2418  } catch (PropertyVetoException exp) {
2419  // In this case, the JDBC driver doesn't support PostgreSQL. Use the generic message here.
2420  throw new TskCoreException(exp.getMessage(), exp);
2422  //don't wrap in new TskCoreException
2423  throw ex;
2424  } catch (Exception exp) {
2425  tryConnect(info); // attempt to connect, throw with user-friendly message if unable
2426  throw new TskCoreException(exp.getMessage(), exp); // throw with generic message if tryConnect() was successful
2427  }
2428  }
2429 
2439  public static SleuthkitCase newCase(String dbPath) throws TskCoreException {
2440  try {
2441  CaseDatabaseFactory factory = new CaseDatabaseFactory(dbPath);
2442  factory.createCaseDatabase();
2443 
2444  SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath);
2445  return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE);
2446  } catch (Exception ex) {
2447  throw new TskCoreException("Failed to create case database at " + dbPath, ex);
2448  }
2449  }
2450 
2466  public static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath) throws TskCoreException {
2467  String databaseName = createCaseDataBaseName(caseName);
2468  try {
2481  CaseDatabaseFactory factory = new CaseDatabaseFactory(databaseName, info);
2482  factory.createCaseDatabase();
2483 
2484  final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info);
2485  return new SleuthkitCase(info.getHost(), Integer.parseInt(info.getPort()),
2486  databaseName, info.getUserName(), info.getPassword(), caseHandle, caseDirPath, info.getDbType());
2487  } catch (PropertyVetoException exp) {
2488  // In this case, the JDBC driver doesn't support PostgreSQL. Use the generic message here.
2489  throw new TskCoreException(exp.getMessage(), exp);
2490  } catch (Exception exp) {
2491  tryConnect(info); // attempt to connect, throw with user-friendly message if unable
2492  throw new TskCoreException(exp.getMessage(), exp); // throw with generic message if tryConnect() was successful
2493  }
2494  }
2495 
2505  private static String createCaseDataBaseName(String candidateDbName) {
2506  String dbName;
2507  if (!candidateDbName.isEmpty()) {
2508  /*
2509  * Replace all non-ASCII characters.
2510  */
2511  dbName = candidateDbName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS
2512 
2513  /*
2514  * Replace all control characters.
2515  */
2516  dbName = dbName.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS
2517 
2518  /*
2519  * Replace /, \, :, ?, space, ' ".
2520  */
2521  dbName = dbName.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS
2522 
2523  /*
2524  * Make it all lowercase.
2525  */
2526  dbName = dbName.toLowerCase();
2527 
2528  /*
2529  * Must start with letter or underscore. If not, prepend an
2530  * underscore.
2531  */
2532  if ((dbName.length() > 0 && !(Character.isLetter(dbName.codePointAt(0))) && !(dbName.codePointAt(0) == '_'))) {
2533  dbName = "_" + dbName;
2534  }
2535 
2536  /*
2537  * Truncate to 63 - 16 = 47 chars to accomodate a timestamp for
2538  * uniqueness.
2539  */
2540  if (dbName.length() > MAX_DB_NAME_LEN_BEFORE_TIMESTAMP) {
2541  dbName = dbName.substring(0, MAX_DB_NAME_LEN_BEFORE_TIMESTAMP);
2542  }
2543 
2544  } else {
2545  /*
2546  * Must start with letter or underscore.
2547  */
2548  dbName = "_";
2549  }
2550  /*
2551  * Add the time stmap.
2552  */
2553  SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
2554  Date date = new Date();
2555  dbName = dbName + "_" + dateFormat.format(date);
2556 
2557  return dbName;
2558  }
2559 
2567  public Examiner getCurrentExaminer() throws TskCoreException {
2568 
2569  // return cached value if there's one
2570  if (cachedCurrentExaminer != null) {
2571  return cachedCurrentExaminer;
2572  }
2573  String loginName = System.getProperty("user.name");
2574  if (loginName == null || loginName.isEmpty()) {
2575  throw new TskCoreException("Failed to determine logged in user name.");
2576  }
2577 
2578  CaseDbConnection connection = connections.getConnection();
2580  ResultSet resultSet = null;
2581  try {
2582  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_EXAMINER_BY_LOGIN_NAME);
2583  statement.clearParameters();
2584  statement.setString(1, loginName);
2585  resultSet = connection.executeQuery(statement);
2586  if (resultSet.next()) {
2587  cachedCurrentExaminer = new Examiner(resultSet.getLong("examiner_id"), resultSet.getString("login_name"), resultSet.getString("display_name"));
2588  return cachedCurrentExaminer;
2589  } else {
2590  throw new TskCoreException("Error getting examaminer for name = " + loginName);
2591  }
2592 
2593  } catch (SQLException ex) {
2594  throw new TskCoreException("Error getting examaminer for name = " + loginName, ex);
2595  } finally {
2596  closeResultSet(resultSet);
2597  connection.close();
2599  }
2600 
2601  }
2602 
2612  Examiner getExaminerById(long id) throws TskCoreException {
2613 
2614  CaseDbConnection connection = connections.getConnection();
2616  ResultSet resultSet = null;
2617  try {
2618  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_EXAMINER_BY_ID);
2619  statement.clearParameters();
2620  statement.setLong(1, id);
2621  resultSet = connection.executeQuery(statement);
2622  if (resultSet.next()) {
2623  return new Examiner(resultSet.getLong("examiner_id"), resultSet.getString("login_name"), resultSet.getString("full_name"));
2624  } else {
2625  throw new TskCoreException("Error getting examaminer for id = " + id);
2626  }
2627  } catch (SQLException ex) {
2628  throw new TskCoreException("Error getting examaminer for id = " + id, ex);
2629  } finally {
2630  closeResultSet(resultSet);
2631  connection.close();
2633  }
2634  }
2635 
2653  public AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath) {
2654  return this.caseHandle.initAddImageProcess(timeZone, addUnallocSpace, noFatFsOrphans, imageCopyPath, this);
2655  }
2656 
2665  public List<Content> getRootObjects() throws TskCoreException {
2666  CaseDbConnection connection = connections.getConnection();
2668  Statement s = null;
2669  ResultSet rs = null;
2670  try {
2671  s = connection.createStatement();
2672  rs = connection.executeQuery(s, "SELECT obj_id, type FROM tsk_objects " //NON-NLS
2673  + "WHERE par_obj_id IS NULL"); //NON-NLS
2674  Collection<ObjectInfo> infos = new ArrayList<ObjectInfo>();
2675  while (rs.next()) {
2676  infos.add(new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")))); //NON-NLS
2677  }
2678 
2679  List<Content> rootObjs = new ArrayList<Content>();
2680  for (ObjectInfo i : infos) {
2681  if (null != i.type) {
2682  switch (i.type) {
2683  case IMG:
2684  rootObjs.add(getImageById(i.id));
2685  break;
2686  case ABSTRACTFILE:
2687  // Check if virtual dir for local files.
2688  AbstractFile af = getAbstractFileById(i.id);
2689  if (af instanceof VirtualDirectory) {
2690  rootObjs.add(af);
2691  } else {
2692  throw new TskCoreException("Parentless object has wrong type to be a root (ABSTRACTFILE, but not VIRTUAL_DIRECTORY: " + i.type);
2693  }
2694  break;
2695  case REPORT:
2696  break;
2697  default:
2698  throw new TskCoreException("Parentless object has wrong type to be a root: " + i.type);
2699  }
2700  }
2701  }
2702  return rootObjs;
2703  } catch (SQLException ex) {
2704  throw new TskCoreException("Error getting root objects", ex);
2705  } finally {
2706  closeResultSet(rs);
2707  closeStatement(s);
2708  connection.close();
2710  }
2711  }
2712 
2724  List<Long> getDataSourceObjIds(String deviceId) throws TskCoreException {
2725 
2726  // check cached map first
2727  synchronized (deviceIdToDatasourceObjIdMap) {
2728  if (deviceIdToDatasourceObjIdMap.containsKey(deviceId)) {
2729  return new ArrayList<Long>(deviceIdToDatasourceObjIdMap.get(deviceId));
2730  }
2731 
2732  CaseDbConnection connection = connections.getConnection();
2734  Statement s = null;
2735  ResultSet rs = null;
2736  try {
2737  s = connection.createStatement();
2738  rs = connection.executeQuery(s, "SELECT obj_id FROM data_source_info WHERE device_id = '" + deviceId + "'"); //NON-NLS
2739  List<Long> dataSourceObjIds = new ArrayList<Long>();
2740  while (rs.next()) {
2741  dataSourceObjIds.add(rs.getLong("obj_id"));
2742 
2743  // Add to map of deviceID to data_source_obj_id.
2744  long ds_obj_id = rs.getLong("obj_id");
2745  if (deviceIdToDatasourceObjIdMap.containsKey(deviceId)) {
2746  deviceIdToDatasourceObjIdMap.get(deviceId).add(ds_obj_id);
2747  } else {
2748  deviceIdToDatasourceObjIdMap.put(deviceId, new HashSet<Long>(Arrays.asList(ds_obj_id)));
2749  }
2750  }
2751  return dataSourceObjIds;
2752  } catch (SQLException ex) {
2753  throw new TskCoreException("Error getting data sources", ex);
2754  } finally {
2755  closeResultSet(rs);
2756  closeStatement(s);
2757  connection.close();
2759  }
2760  }
2761  }
2762 
2779  public List<DataSource> getDataSources() throws TskCoreException {
2780  CaseDbConnection connection = connections.getConnection();
2782  Statement statement = null;
2783  ResultSet resultSet = null;
2784  Statement statement2 = null;
2785  ResultSet resultSet2 = null;
2786  try {
2787  statement = connection.createStatement();
2788  statement2 = connection.createStatement();
2789  resultSet = connection.executeQuery(statement,
2790  "SELECT ds.obj_id, ds.device_id, ds.time_zone, img.type, img.ssize, img.size, img.md5, img.sha1, img.sha256, img.display_name "
2791  + "FROM data_source_info AS ds "
2792  + "LEFT JOIN tsk_image_info AS img "
2793  + "ON ds.obj_id = img.obj_id"); //NON-NLS
2794 
2795  List<DataSource> dataSourceList = new ArrayList<DataSource>();
2796  Map<Long, List<String>> imagePathsMap = getImagePaths();
2797 
2798  while (resultSet.next()) {
2799  DataSource dataSource;
2800  Long objectId = resultSet.getLong("obj_id");
2801  String deviceId = resultSet.getString("device_id");
2802  String timezone = resultSet.getString("time_zone");
2803  String type = resultSet.getString("type");
2804 
2805  if (type == null) {
2806  /*
2807  * No data found in 'tsk_image_info', so we build a
2808  * LocalFilesDataSource.
2809  */
2810 
2811  resultSet2 = connection.executeQuery(statement2, "SELECT name FROM tsk_files WHERE tsk_files.obj_id = " + objectId); //NON-NLS
2812  String dsName = (resultSet2.next()) ? resultSet2.getString("name") : "";
2813  resultSet2.close();
2814 
2818  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
2819  | TSK_FS_META_FLAG_ENUM.USED.getValue());
2820  String parentPath = "/"; //NON-NLS
2821  dataSource = new LocalFilesDataSource(this, objectId, objectId, deviceId, dsName, dirType, metaType, dirFlag, metaFlags, timezone, null, FileKnown.UNKNOWN, parentPath);
2822  } else {
2823  /*
2824  * Data found in 'tsk_image_info', so we build an Image.
2825  */
2826  Long ssize = resultSet.getLong("ssize");
2827  Long size = resultSet.getLong("size");
2828  String md5 = resultSet.getString("md5");
2829  String sha1 = resultSet.getString("sha1");
2830  String sha256 = resultSet.getString("sha256");
2831  String name = resultSet.getString("display_name");
2832 
2833  List<String> imagePaths = imagePathsMap.get(objectId);
2834  if (name == null) {
2835  if (imagePaths.size() > 0) {
2836  String path = imagePaths.get(0);
2837  name = (new java.io.File(path)).getName();
2838  } else {
2839  name = "";
2840  }
2841  }
2842 
2843  dataSource = new Image(this, objectId, Long.valueOf(type), deviceId, ssize, name,
2844  imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
2845  }
2846 
2847  dataSourceList.add(dataSource);
2848  }
2849 
2850  return dataSourceList;
2851 
2852  } catch (SQLException ex) {
2853  throw new TskCoreException("Error getting data sources", ex);
2854  } finally {
2855  closeResultSet(resultSet);
2856  closeStatement(statement);
2857  closeResultSet(resultSet2);
2858  closeStatement(statement2);
2859  connection.close();
2861  }
2862  }
2863 
2883  public DataSource getDataSource(long objectId) throws TskDataException, TskCoreException {
2884  DataSource dataSource = null;
2885  CaseDbConnection connection = connections.getConnection();
2887  Statement statement = null;
2888  ResultSet resultSet = null;
2889  Statement statement2 = null;
2890  ResultSet resultSet2 = null;
2891  try {
2892  statement = connection.createStatement();
2893  statement2 = connection.createStatement();
2894  resultSet = connection.executeQuery(statement,
2895  "SELECT ds.device_id, ds.time_zone, img.type, img.ssize, img.size, img.md5, img.sha1, img.sha256, img.display_name "
2896  + "FROM data_source_info AS ds "
2897  + "LEFT JOIN tsk_image_info AS img "
2898  + "ON ds.obj_id = img.obj_id "
2899  + "WHERE ds.obj_id = " + objectId); //NON-NLS
2900  if (resultSet.next()) {
2901  String deviceId = resultSet.getString("device_id");
2902  String timezone = resultSet.getString("time_zone");
2903  String type = resultSet.getString("type");
2904 
2905  if (type == null) {
2906  /*
2907  * No data found in 'tsk_image_info', so we build an
2908  * LocalFilesDataSource.
2909  */
2910 
2911  resultSet2 = connection.executeQuery(statement2, "SELECT name FROM tsk_files WHERE tsk_files.obj_id = " + objectId); //NON-NLS
2912  String dsName = (resultSet2.next()) ? resultSet2.getString("name") : "";
2913 
2917  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
2918  | TSK_FS_META_FLAG_ENUM.USED.getValue());
2919  String parentPath = "/"; //NON-NLS
2920  dataSource = new LocalFilesDataSource(this, objectId, objectId, deviceId, dsName, dirType, metaType, dirFlag, metaFlags, timezone, null, FileKnown.UNKNOWN, parentPath);
2921  } else {
2922  /*
2923  * Data found in 'tsk_image_info', so we build an Image.
2924  */
2925  Long ssize = resultSet.getLong("ssize");
2926  Long size = resultSet.getLong("size");
2927  String md5 = resultSet.getString("md5");
2928  String sha1 = resultSet.getString("sha1");
2929  String sha256 = resultSet.getString("sha256");
2930  String name = resultSet.getString("display_name");
2931 
2932  List<String> imagePaths = getImagePathsById(objectId);
2933  if (name == null) {
2934  if (imagePaths.size() > 0) {
2935  String path = imagePaths.get(0);
2936  name = (new java.io.File(path)).getName();
2937  } else {
2938  name = "";
2939  }
2940  }
2941 
2942  dataSource = new Image(this, objectId, Long.valueOf(type), deviceId, ssize, name,
2943  imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
2944  }
2945  } else {
2946  throw new TskDataException(String.format("There is no data source with obj_id = %d", objectId));
2947  }
2948  } catch (SQLException ex) {
2949  throw new TskCoreException(String.format("Error getting data source with obj_id = %d", objectId), ex);
2950  } finally {
2951  closeResultSet(resultSet);
2952  closeStatement(statement);
2953  closeResultSet(resultSet2);
2954  closeStatement(statement2);
2955  connection.close();
2957  }
2958 
2959  return dataSource;
2960  }
2961 
2972  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(int artifactTypeID) throws TskCoreException {
2973  return getArtifactsHelper("blackboard_artifacts.artifact_type_id = " + artifactTypeID);
2974  }
2975 
2986  public long getBlackboardArtifactsCount(long objId) throws TskCoreException {
2987  CaseDbConnection connection = connections.getConnection();
2989  ResultSet rs = null;
2990  try {
2991  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ?
2992  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_FROM_SOURCE);
2993  statement.clearParameters();
2994  statement.setLong(1, objId);
2995  rs = connection.executeQuery(statement);
2996  long count = 0;
2997  if (rs.next()) {
2998  count = rs.getLong("count");
2999  }
3000  return count;
3001  } catch (SQLException ex) {
3002  throw new TskCoreException("Error getting number of blackboard artifacts by content", ex);
3003  } finally {
3004  closeResultSet(rs);
3005  connection.close();
3007  }
3008  }
3009 
3020  public long getBlackboardArtifactsTypeCount(int artifactTypeID) throws TskCoreException {
3021  CaseDbConnection connection = connections.getConnection();
3023  ResultSet rs = null;
3024  try {
3025  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ?
3026  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_OF_TYPE);
3027  statement.clearParameters();
3028  statement.setInt(1, artifactTypeID);
3029  rs = connection.executeQuery(statement);
3030  long count = 0;
3031  if (rs.next()) {
3032  count = rs.getLong("count");
3033  }
3034  return count;
3035  } catch (SQLException ex) {
3036  throw new TskCoreException("Error getting number of blackboard artifacts by type", ex);
3037  } finally {
3038  closeResultSet(rs);
3039  connection.close();
3041  }
3042  }
3043 
3055  public long getBlackboardArtifactsTypeCount(int artifactTypeID, long dataSourceID) throws TskCoreException {
3056  CaseDbConnection connection = connections.getConnection();
3058  ResultSet rs = null;
3059  try {
3060  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ?
3061  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_OF_TYPE_BY_DATA_SOURCE);
3062  statement.clearParameters();
3063  statement.setInt(2, artifactTypeID);
3064  statement.setLong(1, dataSourceID);
3065  rs = connection.executeQuery(statement);
3066  long count = 0;
3067  if (rs.next()) {
3068  count = rs.getLong("count");
3069  }
3070  return count;
3071  } catch (SQLException ex) {
3072  throw new TskCoreException(String.format("Error getting number of blackboard artifacts by type (%d) and data source (%d)", artifactTypeID, dataSourceID), ex);
3073  } finally {
3074  closeResultSet(rs);
3075  connection.close();
3077  }
3078  }
3079 
3094  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value) throws TskCoreException {
3095  CaseDbConnection connection = connections.getConnection();
3097  Statement s = null;
3098  ResultSet rs = null;
3099  try {
3100  s = connection.createStatement();
3101  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3102  + "arts.obj_id AS obj_id, arts.artifact_obj_id AS artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3103  + "types.type_name AS type_name, types.display_name AS display_name, "//NON-NLS
3104  + " arts.review_status_id AS review_status_id " //NON-NLS
3105  + "FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3106  + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3107  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3108  + " AND attrs.value_text = '" + value + "'"
3109  + " AND types.artifact_type_id=arts.artifact_type_id"
3110  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()); //NON-NLS
3111  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3112  while (rs.next()) {
3113  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3114  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3115  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3116  }
3117  return artifacts;
3118  } catch (SQLException ex) {
3119  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3120  } finally {
3121  closeResultSet(rs);
3122  closeStatement(s);
3123  connection.close();
3125  }
3126  }
3127 
3145  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String subString, boolean startsWith) throws TskCoreException {
3146  String valSubStr = "%" + subString; //NON-NLS
3147  if (startsWith == false) {
3148  valSubStr += "%"; //NON-NLS
3149  }
3150  CaseDbConnection connection = connections.getConnection();
3152  Statement s = null;
3153  ResultSet rs = null;
3154  try {
3155  s = connection.createStatement();
3156  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3157  + " arts.obj_id AS obj_id, arts.artifact_obj_id AS artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, " //NON-NLS
3158  + " types.type_name AS type_name, types.display_name AS display_name, " //NON-NLS
3159  + " arts.review_status_id AS review_status_id " //NON-NLS
3160  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3161  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3162  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3163  + " AND LOWER(attrs.value_text) LIKE LOWER('" + valSubStr + "')"
3164  + " AND types.artifact_type_id=arts.artifact_type_id "
3165  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3166  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3167  while (rs.next()) {
3168  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3169  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3170  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3171  }
3172  return artifacts;
3173  } catch (SQLException ex) {
3174  throw new TskCoreException("Error getting blackboard artifacts by attribute. " + ex.getMessage(), ex);
3175  } finally {
3176  closeResultSet(rs);
3177  closeStatement(s);
3178  connection.close();
3180  }
3181  }
3182 
3197  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, int value) throws TskCoreException {
3198  CaseDbConnection connection = connections.getConnection();
3200  Statement s = null;
3201  ResultSet rs = null;
3202  try {
3203  s = connection.createStatement();
3204  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3205  + " arts.obj_id AS obj_id, arts.artifact_obj_id AS artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3206  + " types.type_name AS type_name, types.display_name AS display_name, "
3207  + " arts.review_status_id AS review_status_id "//NON-NLS
3208  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3209  + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3210  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3211  + " AND attrs.value_int32 = " + value //NON-NLS
3212  + " AND types.artifact_type_id=arts.artifact_type_id "
3213  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3214  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3215  while (rs.next()) {
3216  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3217  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3218  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3219  }
3220  return artifacts;
3221  } catch (SQLException ex) {
3222  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3223  } finally {
3224  closeResultSet(rs);
3225  closeStatement(s);
3226  connection.close();
3228  }
3229  }
3230 
3245  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, long value) throws TskCoreException {
3246  CaseDbConnection connection = connections.getConnection();
3248  Statement s = null;
3249  ResultSet rs = null;
3250  try {
3251  s = connection.createStatement();
3252  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3253  + " arts.obj_id AS obj_id, arts.artifact_obj_id AS artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3254  + " types.type_name AS type_name, types.display_name AS display_name, "
3255  + " arts.review_status_id AS review_status_id "//NON-NLS
3256  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3257  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3258  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3259  + " AND attrs.value_int64 = " + value //NON-NLS
3260  + " AND types.artifact_type_id=arts.artifact_type_id "
3261  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3262  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3263  while (rs.next()) {
3264  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3265  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3266  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3267  }
3268  return artifacts;
3269  } catch (SQLException ex) {
3270  throw new TskCoreException("Error getting blackboard artifacts by attribute. " + ex.getMessage(), ex);
3271  } finally {
3272  closeResultSet(rs);
3273  closeStatement(s);
3274  connection.close();
3276  }
3277  }
3278 
3293  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, double value) throws TskCoreException {
3294  CaseDbConnection connection = connections.getConnection();
3296  Statement s = null;
3297  ResultSet rs = null;
3298  try {
3299  s = connection.createStatement();
3300  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3301  + " arts.obj_id AS obj_id, arts.artifact_obj_id AS artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3302  + " types.type_name AS type_name, types.display_name AS display_name, "
3303  + " arts.review_status_id AS review_status_id "//NON-NLS
3304  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3305  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3306  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3307  + " AND attrs.value_double = " + value //NON-NLS
3308  + " AND types.artifact_type_id=arts.artifact_type_id "
3309  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3310  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3311  while (rs.next()) {
3312  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3313  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3314  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3315  }
3316  return artifacts;
3317  } catch (SQLException ex) {
3318  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3319  } finally {
3320  closeResultSet(rs);
3321  closeStatement(s);
3322  connection.close();
3324  }
3325  }
3326 
3341  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, byte value) throws TskCoreException {
3342  CaseDbConnection connection = connections.getConnection();
3344  Statement s = null;
3345  ResultSet rs = null;
3346  try {
3347  s = connection.createStatement();
3348  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3349  + " arts.obj_id AS obj_id, arts.artifact_obj_id AS artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3350  + " types.type_name AS type_name, types.display_name AS display_name, "
3351  + " arts.review_status_id AS review_status_id "//NON-NLS
3352  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3353  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3354  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3355  + " AND attrs.value_byte = " + value //NON-NLS
3356  + " AND types.artifact_type_id=arts.artifact_type_id "
3357  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3358  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3359  while (rs.next()) {
3360  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3361  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3362  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3363  }
3364  return artifacts;
3365  } catch (SQLException ex) {
3366  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3367  } finally {
3368  closeResultSet(rs);
3369  closeStatement(s);
3370  connection.close();
3372  }
3373  }
3374 
3382  public Iterable<BlackboardArtifact.Type> getArtifactTypes() throws TskCoreException {
3383  CaseDbConnection connection = connections.getConnection();
3385  Statement s = null;
3386  ResultSet rs = null;
3387  try {
3388  s = connection.createStatement();
3389  rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name FROM blackboard_artifact_types"); //NON-NLS
3390  ArrayList<BlackboardArtifact.Type> artifactTypes = new ArrayList<BlackboardArtifact.Type>();
3391  while (rs.next()) {
3392  artifactTypes.add(new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
3393  rs.getString("type_name"), rs.getString("display_name")));
3394  }
3395  return artifactTypes;
3396  } catch (SQLException ex) {
3397  throw new TskCoreException("Error getting artifact types", ex); //NON-NLS
3398  } finally {
3399  closeResultSet(rs);
3400  closeStatement(s);
3401  connection.close();
3403  }
3404  }
3405 
3414  public ArrayList<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardArtifactTypesInUse() throws TskCoreException {
3415  String typeIdList = "";
3416  for (int i = 0; i < BlackboardArtifact.ARTIFACT_TYPE.values().length; ++i) {
3417  typeIdList += BlackboardArtifact.ARTIFACT_TYPE.values()[i].getTypeID();
3418  if (i < BlackboardArtifact.ARTIFACT_TYPE.values().length - 1) {
3419  typeIdList += ", ";
3420  }
3421  }
3422  String query = "SELECT DISTINCT artifact_type_id FROM blackboard_artifacts "
3423  + "WHERE artifact_type_id IN (" + typeIdList + ")";
3424  CaseDbConnection connection = connections.getConnection();
3426  Statement s = null;
3427  ResultSet rs = null;
3428  try {
3429  s = connection.createStatement();
3430  rs = connection.executeQuery(s, query);
3431  ArrayList<BlackboardArtifact.ARTIFACT_TYPE> usedArts = new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>();
3432  while (rs.next()) {
3433  usedArts.add(ARTIFACT_TYPE.fromID(rs.getInt("artifact_type_id")));
3434  }
3435  return usedArts;
3436  } catch (SQLException ex) {
3437  throw new TskCoreException("Error getting artifact types in use", ex);
3438  } finally {
3439  closeResultSet(rs);
3440  closeStatement(s);
3441  connection.close();
3443  }
3444  }
3445 
3456  public List<BlackboardArtifact.Type> getArtifactTypesInUse() throws TskCoreException {
3457  CaseDbConnection connection = connections.getConnection();
3459  Statement s = null;
3460  ResultSet rs = null;
3461  try {
3462  s = connection.createStatement();
3463  rs = connection.executeQuery(s,
3464  "SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, "
3465  + "types.type_name AS type_name, types.display_name AS display_name "
3466  + "FROM blackboard_artifact_types AS types "
3467  + "INNER JOIN blackboard_artifacts AS arts "
3468  + "ON arts.artifact_type_id = types.artifact_type_id"); //NON-NLS
3469  List<BlackboardArtifact.Type> uniqueArtifactTypes = new ArrayList<BlackboardArtifact.Type>();
3470  while (rs.next()) {
3471  uniqueArtifactTypes.add(new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
3472  rs.getString("type_name"), rs.getString("display_name")));
3473  }
3474  return uniqueArtifactTypes;
3475  } catch (SQLException ex) {
3476  throw new TskCoreException("Error getting attribute types", ex);
3477  } finally {
3478  closeResultSet(rs);
3479  closeStatement(s);
3480  connection.close();
3482  }
3483  }
3484 
3492  public List<BlackboardAttribute.Type> getAttributeTypes() throws TskCoreException {
3493  CaseDbConnection connection = connections.getConnection();
3495  Statement s = null;
3496  ResultSet rs = null;
3497  try {
3498  s = connection.createStatement();
3499  rs = connection.executeQuery(s, "SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types"); //NON-NLS
3500  ArrayList<BlackboardAttribute.Type> attribute_types = new ArrayList<BlackboardAttribute.Type>();
3501  while (rs.next()) {
3502  attribute_types.add(new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
3503  rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type"))));
3504  }
3505  return attribute_types;
3506  } catch (SQLException ex) {
3507  throw new TskCoreException("Error getting attribute types", ex);
3508  } finally {
3509  closeResultSet(rs);
3510  closeStatement(s);
3511  connection.close();
3513  }
3514  }
3515 
3527  public int getBlackboardAttributeTypesCount() throws TskCoreException {
3528  CaseDbConnection connection = connections.getConnection();
3530  Statement s = null;
3531  ResultSet rs = null;
3532  try {
3533  s = connection.createStatement();
3534  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM blackboard_attribute_types"); //NON-NLS
3535  int count = 0;
3536  if (rs.next()) {
3537  count = rs.getInt("count");
3538  }
3539  return count;
3540  } catch (SQLException ex) {
3541  throw new TskCoreException("Error getting number of blackboard artifacts by type", ex);
3542  } finally {
3543  closeResultSet(rs);
3544  closeStatement(s);
3545  connection.close();
3547  }
3548  }
3549 
3562  ArrayList<BlackboardArtifact> getArtifactsHelper(String whereClause) throws TskCoreException {
3563  CaseDbConnection connection = connections.getConnection();
3565  ResultSet rs = null;
3566  try {
3567  Statement statement = connection.createStatement();
3568  String query = "SELECT blackboard_artifacts.artifact_id AS artifact_id, "
3569  + "blackboard_artifacts.obj_id AS obj_id, "
3570  + "blackboard_artifacts.artifact_obj_id AS artifact_obj_id, "
3571  + "blackboard_artifacts.data_source_obj_id AS data_source_obj_id, "
3572  + "blackboard_artifact_types.artifact_type_id AS artifact_type_id, "
3573  + "blackboard_artifact_types.type_name AS type_name, "
3574  + "blackboard_artifact_types.display_name AS display_name, "
3575  + "blackboard_artifacts.review_status_id AS review_status_id "
3576  + "FROM blackboard_artifacts, blackboard_artifact_types "
3577  + "WHERE blackboard_artifacts.artifact_type_id = blackboard_artifact_types.artifact_type_id "
3578  + " AND blackboard_artifacts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
3579  + " AND " + whereClause;
3580  rs = connection.executeQuery(statement, query);
3581  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3582  while (rs.next()) {
3583  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3584  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3585  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3586  }
3587  return artifacts;
3588  } catch (SQLException ex) {
3589  throw new TskCoreException("Error getting or creating a blackboard artifact", ex);
3590  } finally {
3591  closeResultSet(rs);
3592  connection.close();
3594  }
3595  }
3596 
3609  private long getArtifactsCountHelper(int artifactTypeID, long obj_id) throws TskCoreException {
3610  CaseDbConnection connection = connections.getConnection();
3612  ResultSet rs = null;
3613  try {
3614  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND artifact_type_id = ?
3615  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_SOURCE_AND_TYPE);
3616  statement.clearParameters();
3617  statement.setLong(1, obj_id);
3618  statement.setInt(2, artifactTypeID);
3619  rs = connection.executeQuery(statement);
3620  long count = 0;
3621  if (rs.next()) {
3622  count = rs.getLong("count");
3623  }
3624  return count;
3625  } catch (SQLException ex) {
3626  throw new TskCoreException("Error getting blackboard artifact count", ex);
3627  } finally {
3628  closeResultSet(rs);
3629  connection.close();
3631  }
3632  }
3633 
3646  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(String artifactTypeName, long obj_id) throws TskCoreException {
3647  return getArtifactsHelper("blackboard_artifacts.obj_id = " + obj_id + " AND blackboard_artifact_types.type_name = '" + artifactTypeName + "';");
3648  }
3649 
3662  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(int artifactTypeID, long obj_id) throws TskCoreException {
3663  return getArtifactsHelper("blackboard_artifacts.obj_id = " + obj_id + " AND blackboard_artifact_types.artifact_type_id = " + artifactTypeID + ";");
3664  }
3665 
3678  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
3679  return getBlackboardArtifacts(artifactType.getTypeID(), obj_id);
3680  }
3681 
3694  public long getBlackboardArtifactsCount(String artifactTypeName, long obj_id) throws TskCoreException {
3695  int artifactTypeID = this.getArtifactType(artifactTypeName).getTypeID();
3696  if (artifactTypeID == -1) {
3697  return 0;
3698  }
3699  return getArtifactsCountHelper(artifactTypeID, obj_id);
3700  }
3701 
3714  public long getBlackboardArtifactsCount(int artifactTypeID, long obj_id) throws TskCoreException {
3715  return getArtifactsCountHelper(artifactTypeID, obj_id);
3716  }
3717 
3730  public long getBlackboardArtifactsCount(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
3731  return getArtifactsCountHelper(artifactType.getTypeID(), obj_id);
3732  }
3733 
3745  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(String artifactTypeName) throws TskCoreException {
3746  return getArtifactsHelper("blackboard_artifact_types.type_name = '" + artifactTypeName + "';");
3747  }
3748 
3760  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType) throws TskCoreException {
3761  return getArtifactsHelper("blackboard_artifact_types.artifact_type_id = " + artifactType.getTypeID() + ";");
3762  }
3763 
3777  public List<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value) throws TskCoreException {
3778  CaseDbConnection connection = connections.getConnection();
3780  Statement s = null;
3781  ResultSet rs = null;
3782  try {
3783  s = connection.createStatement();
3784  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3785  + "arts.obj_id AS obj_id, arts.artifact_obj_id as artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3786  + "types.type_name AS type_name, types.display_name AS display_name,"
3787  + "arts.review_status_id AS review_status_id "//NON-NLS
3788  + "FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3789  + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3790  + "AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3791  + " AND arts.artifact_type_id = " + artifactType.getTypeID() //NON-NLS
3792  + " AND attrs.value_text = '" + value + "'" //NON-NLS
3793  + " AND types.artifact_type_id=arts.artifact_type_id"
3794  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3795  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3796  while (rs.next()) {
3797  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3798  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3799  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3800  }
3801  return artifacts;
3802  } catch (SQLException ex) {
3803  throw new TskCoreException("Error getting blackboard artifacts by artifact type and attribute. " + ex.getMessage(), ex);
3804  } finally {
3805  closeResultSet(rs);
3806  closeStatement(s);
3807  connection.close();
3809  }
3810  }
3811 
3822  public BlackboardArtifact getBlackboardArtifact(long artifactID) throws TskCoreException {
3823  CaseDbConnection connection = connections.getConnection();
3825  ResultSet rs = null;
3826  Statement s;
3827  try {
3828  s = connection.createStatement();
3829  rs = connection.executeQuery(s, "SELECT arts.artifact_id AS artifact_id, "
3830  + "arts.obj_id AS obj_id, arts.artifact_obj_id as artifact_obj_id, arts.data_source_obj_id AS data_source_obj_id, arts.artifact_type_id AS artifact_type_id, "
3831  + "types.type_name AS type_name, types.display_name AS display_name,"
3832  + "arts.review_status_id AS review_status_id "//NON-NLS
3833  + "FROM blackboard_artifacts AS arts, blackboard_artifact_types AS types "
3834  + "WHERE arts.artifact_id = " + artifactID
3835  + " AND arts.artifact_type_id = types.artifact_type_id");
3836  if (rs.next()) {
3837  return new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3838  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3839  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")));
3840  } else {
3841  /*
3842  * I think this should actually return null (or Optional) when
3843  * there is no artifact with the given id, but it looks like
3844  * existing code is not expecting that. -jm
3845  */
3846  throw new TskCoreException("No blackboard artifact with id " + artifactID);
3847  }
3848  } catch (SQLException ex) {
3849  throw new TskCoreException("Error getting a blackboard artifact. " + ex.getMessage(), ex);
3850  } finally {
3851  closeResultSet(rs);
3852  connection.close();
3854  }
3855  }
3856 
3865  public void addBlackboardAttribute(BlackboardAttribute attr, int artifactTypeId) throws TskCoreException {
3866  CaseDbConnection connection = connections.getConnection();
3868  try {
3869  addBlackBoardAttribute(attr, artifactTypeId, connection);
3870  } catch (SQLException ex) {
3871  throw new TskCoreException("Error adding blackboard attribute " + attr.toString(), ex);
3872  } finally {
3873  connection.close();
3875  }
3876  }
3877 
3887  public void addBlackboardAttributes(Collection<BlackboardAttribute> attributes, int artifactTypeId) throws TskCoreException {
3888  CaseDbConnection connection = connections.getConnection();
3890  try {
3891  connection.beginTransaction();
3892  for (final BlackboardAttribute attr : attributes) {
3893  addBlackBoardAttribute(attr, artifactTypeId, connection);
3894  }
3895  connection.commitTransaction();
3896  } catch (SQLException ex) {
3897  connection.rollbackTransaction();
3898  throw new TskCoreException("Error adding blackboard attributes", ex);
3899  } finally {
3900  connection.close();
3902  }
3903  }
3904 
3905  private void addBlackBoardAttribute(BlackboardAttribute attr, int artifactTypeId, CaseDbConnection connection) throws SQLException, TskCoreException {
3906  PreparedStatement statement;
3907  switch (attr.getAttributeType().getValueType()) {
3908  case STRING:
3909  case JSON:
3910  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_STRING_ATTRIBUTE);
3911  statement.clearParameters();
3912  statement.setString(7, attr.getValueString());
3913  break;
3914  case BYTE:
3915  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_BYTE_ATTRIBUTE);
3916  statement.clearParameters();
3917  statement.setBytes(7, attr.getValueBytes());
3918  break;
3919  case INTEGER:
3920  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INT_ATTRIBUTE);
3921  statement.clearParameters();
3922  statement.setInt(7, attr.getValueInt());
3923  break;
3924  case LONG:
3925  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LONG_ATTRIBUTE);
3926  statement.clearParameters();
3927  statement.setLong(7, attr.getValueLong());
3928  break;
3929  case DOUBLE:
3930  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DOUBLE_ATTRIBUTE);
3931  statement.clearParameters();
3932  statement.setDouble(7, attr.getValueDouble());
3933  break;
3934  case DATETIME:
3935  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LONG_ATTRIBUTE);
3936  statement.clearParameters();
3937  statement.setLong(7, attr.getValueLong());
3938  break;
3939  default:
3940  throw new TskCoreException("Unrecognized artifact attribute value type");
3941  }
3942  statement.setLong(1, attr.getArtifactID());
3943  statement.setInt(2, artifactTypeId);
3944  statement.setString(3, attr.getSourcesCSV());
3945  statement.setString(4, "");
3946  statement.setInt(5, attr.getAttributeType().getTypeID());
3947  statement.setLong(6, attr.getAttributeType().getValueType().getType());
3948  connection.executeUpdate(statement);
3949  }
3950 
3961  String addSourceToArtifactAttribute(BlackboardAttribute attr, String source) throws TskCoreException {
3962  /*
3963  * WARNING: This is a temporary implementation that is not safe and
3964  * denormalizes the case datbase.
3965  *
3966  * TODO (JIRA-2294): Provide a safe and normalized solution to tracking
3967  * the sources of artifact attributes.
3968  */
3969  if (null == source || source.isEmpty()) {
3970  throw new TskCoreException("Attempt to add null or empty source module name to artifact attribute");
3971  }
3972  CaseDbConnection connection = connections.getConnection();
3974  Statement queryStmt = null;
3975  Statement updateStmt = null;
3976  ResultSet result = null;
3977  String newSources = "";
3978  try {
3979  connection.beginTransaction();
3980  String valueClause = "";
3981  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType = attr.getAttributeType().getValueType();
3982  if (BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE != valueType) {
3983  switch (valueType) {
3984  case STRING:
3985  case JSON:
3986  valueClause = " value_text = '" + escapeSingleQuotes(attr.getValueString()) + "'";
3987  break;
3988  case INTEGER:
3989  valueClause = " value_int32 = " + attr.getValueInt();
3990  break;
3991  case LONG:
3992  case DATETIME:
3993  valueClause = " value_int64 = " + attr.getValueLong();
3994  break;
3995  case DOUBLE:
3996  valueClause = " value_double = " + attr.getValueDouble();
3997  break;
3998  default:
3999  throw new TskCoreException(String.format("Unrecognized value type for attribute %s", attr.getDisplayString()));
4000  }
4001  String query = "SELECT source FROM blackboard_attributes WHERE"
4002  + " artifact_id = " + attr.getArtifactID()
4003  + " AND attribute_type_id = " + attr.getAttributeType().getTypeID()
4004  + " AND value_type = " + attr.getAttributeType().getValueType().getType()
4005  + " AND " + valueClause + ";";
4006  queryStmt = connection.createStatement();
4007  updateStmt = connection.createStatement();
4008  result = connection.executeQuery(queryStmt, query);
4009  } else {
4010  /*
4011  * SELECT source FROM blackboard_attributes WHERE artifact_id =
4012  * ? AND attribute_type_id = ? AND value_type = 4 AND value_byte
4013  * = ?
4014  */
4015  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ATTR_BY_VALUE_BYTE);
4016  statement.clearParameters();
4017  statement.setLong(1, attr.getArtifactID());
4018  statement.setLong(2, attr.getAttributeType().getTypeID());
4019  statement.setBytes(3, attr.getValueBytes());
4020  result = connection.executeQuery(statement);
4021  }
4022  while (result.next()) {
4023  String oldSources = result.getString("source");
4024  if (null != oldSources && !oldSources.isEmpty()) {
4025  Set<String> uniqueSources = new HashSet<String>(Arrays.asList(oldSources.split(",")));
4026  if (!uniqueSources.contains(source)) {
4027  newSources = oldSources + "," + source;
4028  } else {
4029  newSources = oldSources;
4030  }
4031  } else {
4032  newSources = source;
4033  }
4034  if (BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE != valueType) {
4035  String update = "UPDATE blackboard_attributes SET source = '" + newSources + "' WHERE"
4036  + " artifact_id = " + attr.getArtifactID()
4037  + " AND attribute_type_id = " + attr.getAttributeType().getTypeID()
4038  + " AND value_type = " + attr.getAttributeType().getValueType().getType()
4039  + " AND " + valueClause + ";";
4040  connection.executeUpdate(updateStmt, update);
4041  } else {
4042  /*
4043  * UPDATE blackboard_attributes SET source = ? WHERE
4044  * artifact_id = ? AND attribute_type_id = ? AND value_type
4045  * = 4 AND value_byte = ?
4046  */
4047  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ATTR_BY_VALUE_BYTE);
4048  statement.clearParameters();
4049  statement.setString(1, newSources);
4050  statement.setLong(2, attr.getArtifactID());
4051  statement.setLong(3, attr.getAttributeType().getTypeID());
4052  statement.setBytes(4, attr.getValueBytes());
4053  connection.executeUpdate(statement);
4054  }
4055  }
4056  connection.commitTransaction();
4057  return newSources;
4058  } catch (SQLException ex) {
4059  connection.rollbackTransaction();
4060  throw new TskCoreException(String.format("Error adding source module to attribute %s", attr.getDisplayString()), ex);
4061  } finally {
4062  closeResultSet(result);
4063  closeStatement(updateStmt);
4064  closeStatement(queryStmt);
4065  connection.close();
4067  }
4068  }
4069 
4084  public BlackboardAttribute.Type addArtifactAttributeType(String attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws TskCoreException, TskDataException {
4085  CaseDbConnection connection = connections.getConnection();
4087  Statement s = null;
4088  ResultSet rs = null;
4089  try {
4090  connection.beginTransaction();
4091  s = connection.createStatement();
4092  rs = connection.executeQuery(s, "SELECT attribute_type_id FROM blackboard_attribute_types WHERE type_name = '" + attrTypeString + "'"); //NON-NLS
4093  if (!rs.next()) {
4094  rs.close();
4095  rs = connection.executeQuery(s, "SELECT MAX(attribute_type_id) AS highest_id FROM blackboard_attribute_types");
4096  int maxID = 0;
4097  if (rs.next()) {
4098  maxID = rs.getInt("highest_id");
4099  if (maxID < MIN_USER_DEFINED_TYPE_ID) {
4100  maxID = MIN_USER_DEFINED_TYPE_ID;
4101  } else {
4102  maxID++;
4103  }
4104  }
4105  connection.executeUpdate(s, "INSERT INTO blackboard_attribute_types (attribute_type_id, type_name, display_name, value_type) VALUES ('" + maxID + "', '" + attrTypeString + "', '" + displayName + "', '" + valueType.getType() + "')"); //NON-NLS
4106  BlackboardAttribute.Type type = new BlackboardAttribute.Type(maxID, attrTypeString, displayName, valueType);
4107  this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
4108  this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
4109  connection.commitTransaction();
4110  return type;
4111  } else {
4112  throw new TskDataException("The attribute type that was added was already within the system.");
4113  }
4114 
4115  } catch (SQLException ex) {
4116  connection.rollbackTransaction();
4117  throw new TskCoreException("Error adding attribute type", ex);
4118  } finally {
4119  closeResultSet(rs);
4120  closeStatement(s);
4121  connection.close();
4123  }
4124  }
4125 
4136  public BlackboardAttribute.Type getAttributeType(String attrTypeName) throws TskCoreException {
4137  if (this.typeNameToAttributeTypeMap.containsKey(attrTypeName)) {
4138  return this.typeNameToAttributeTypeMap.get(attrTypeName);
4139  }
4140  CaseDbConnection connection = connections.getConnection();
4142  Statement s = null;
4143  ResultSet rs = null;
4144  try {
4145  s = connection.createStatement();
4146  rs = connection.executeQuery(s, "SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName + "'"); //NON-NLS
4147  BlackboardAttribute.Type type = null;
4148  if (rs.next()) {
4149  type = new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
4150  rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type")));
4151  this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
4152  this.typeNameToAttributeTypeMap.put(attrTypeName, type);
4153  }
4154  return type;
4155  } catch (SQLException ex) {
4156  throw new TskCoreException("Error getting attribute type id", ex);
4157  } finally {
4158  closeResultSet(rs);
4159  closeStatement(s);
4160  connection.close();
4162  }
4163  }
4164 
4175  private BlackboardAttribute.Type getAttributeType(int typeID) throws TskCoreException {
4176  if (this.typeIdToAttributeTypeMap.containsKey(typeID)) {
4177  return this.typeIdToAttributeTypeMap.get(typeID);
4178  }
4179  CaseDbConnection connection = connections.getConnection();
4181  Statement s = null;
4182  ResultSet rs = null;
4183  try {
4184  s = connection.createStatement();
4185  rs = connection.executeQuery(s, "SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE attribute_type_id = " + typeID + ""); //NON-NLS
4186  BlackboardAttribute.Type type = null;
4187  if (rs.next()) {
4188  type = new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
4189  rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type")));
4190  this.typeIdToAttributeTypeMap.put(typeID, type);
4191  this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
4192  }
4193  return type;
4194  } catch (SQLException ex) {
4195  throw new TskCoreException("Error getting attribute type id", ex);
4196  } finally {
4197  closeResultSet(rs);
4198  closeStatement(s);
4199  connection.close();
4201  }
4202  }
4203 
4214  public BlackboardArtifact.Type getArtifactType(String artTypeName) throws TskCoreException {
4215  if (this.typeNameToArtifactTypeMap.containsKey(artTypeName)) {
4216  return this.typeNameToArtifactTypeMap.get(artTypeName);
4217  }
4218  CaseDbConnection connection = connections.getConnection();
4220  Statement s = null;
4221  ResultSet rs = null;
4222  try {
4223  s = connection.createStatement();
4224  rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name FROM blackboard_artifact_types WHERE type_name = '" + artTypeName + "'"); //NON-NLS
4225  BlackboardArtifact.Type type = null;
4226  if (rs.next()) {
4227  type = new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
4228  rs.getString("type_name"), rs.getString("display_name"));
4229  this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
4230  this.typeNameToArtifactTypeMap.put(artTypeName, type);
4231  }
4232  return type;
4233  } catch (SQLException ex) {
4234  throw new TskCoreException("Error getting artifact type from the database", ex);
4235  } finally {
4236  closeResultSet(rs);
4237  closeStatement(s);
4238  connection.close();
4240  }
4241  }
4242 
4253  BlackboardArtifact.Type getArtifactType(int artTypeId) throws TskCoreException {
4254  if (this.typeIdToArtifactTypeMap.containsKey(artTypeId)) {
4255  return typeIdToArtifactTypeMap.get(artTypeId);
4256  }
4257  CaseDbConnection connection = connections.getConnection();
4259  Statement s = null;
4260  ResultSet rs = null;
4261  try {
4262  s = connection.createStatement();
4263  rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name FROM blackboard_artifact_types WHERE artifact_type_id = " + artTypeId + ""); //NON-NLS
4264  BlackboardArtifact.Type type = null;
4265  if (rs.next()) {
4266  type = new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
4267  rs.getString("type_name"), rs.getString("display_name"));
4268  this.typeIdToArtifactTypeMap.put(artTypeId, type);
4269  this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
4270  }
4271  return type;
4272  } catch (SQLException ex) {
4273  throw new TskCoreException("Error getting artifact type from the database", ex);
4274  } finally {
4275  closeResultSet(rs);
4276  closeStatement(s);
4277  connection.close();
4279  }
4280  }
4281 
4294  public BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName) throws TskCoreException, TskDataException {
4295  CaseDbConnection connection = connections.getConnection();
4297  Statement s = null;
4298  ResultSet rs = null;
4299  try {
4300  connection.beginTransaction();
4301  s = connection.createStatement();
4302  rs = connection.executeQuery(s, "SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = '" + artifactTypeName + "'"); //NON-NLS
4303  if (!rs.next()) {
4304  rs.close();
4305  rs = connection.executeQuery(s, "SELECT MAX(artifact_type_id) AS highest_id FROM blackboard_artifact_types");
4306  int maxID = 0;
4307  if (rs.next()) {
4308  maxID = rs.getInt("highest_id");
4309  if (maxID < MIN_USER_DEFINED_TYPE_ID) {
4310  maxID = MIN_USER_DEFINED_TYPE_ID;
4311  } else {
4312  maxID++;
4313  }
4314  }
4315  connection.executeUpdate(s, "INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name) VALUES ('" + maxID + "', '" + artifactTypeName + "', '" + displayName + "')"); //NON-NLS
4316  BlackboardArtifact.Type type = new BlackboardArtifact.Type(maxID, artifactTypeName, displayName);
4317  this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
4318  this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
4319  connection.commitTransaction();
4320  return type;
4321  } else {
4322  throw new TskDataException("The attribute type that was added was already within the system.");
4323  }
4324  } catch (SQLException ex) {
4325  connection.rollbackTransaction();
4326  throw new TskCoreException("Error adding artifact type", ex);
4327  } finally {
4328  closeResultSet(rs);
4329  closeStatement(s);
4330  connection.close();
4332  }
4333  }
4334 
4335  public ArrayList<BlackboardAttribute> getBlackboardAttributes(final BlackboardArtifact artifact) throws TskCoreException {
4336  CaseDbConnection connection = connections.getConnection();
4338  ResultSet rs = null;
4339  try {
4340  Statement statement = connection.createStatement();
4341  rs = connection.executeQuery(statement, "SELECT attrs.artifact_id AS artifact_id, "
4342  + "attrs.source AS source, attrs.context AS context, attrs.attribute_type_id AS attribute_type_id, "
4343  + "attrs.value_type AS value_type, attrs.value_byte AS value_byte, "
4344  + "attrs.value_text AS value_text, attrs.value_int32 AS value_int32, "
4345  + "attrs.value_int64 AS value_int64, attrs.value_double AS value_double, "
4346  + "types.type_name AS type_name, types.display_name AS display_name "
4347  + "FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id = " + artifact.getArtifactID()
4348  + " AND attrs.attribute_type_id = types.attribute_type_id");
4349  ArrayList<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
4350  while (rs.next()) {
4351  int attributeTypeId = rs.getInt("attribute_type_id");
4352  String attributeTypeName = rs.getString("type_name");
4353  BlackboardAttribute.Type attributeType;
4354  if (this.typeIdToAttributeTypeMap.containsKey(attributeTypeId)) {
4355  attributeType = this.typeIdToAttributeTypeMap.get(attributeTypeId);
4356  } else {
4357  attributeType = new BlackboardAttribute.Type(attributeTypeId, attributeTypeName,
4358  rs.getString("display_name"),
4360  this.typeIdToAttributeTypeMap.put(attributeTypeId, attributeType);
4361  this.typeNameToAttributeTypeMap.put(attributeTypeName, attributeType);
4362  }
4363 
4364  final BlackboardAttribute attr = new BlackboardAttribute(
4365  rs.getLong("artifact_id"),
4366  attributeType,
4367  rs.getString("source"),
4368  rs.getString("context"),
4369  rs.getInt("value_int32"),
4370  rs.getLong("value_int64"),
4371  rs.getDouble("value_double"),
4372  rs.getString("value_text"),
4373  rs.getBytes("value_byte"), this
4374  );
4375  attributes.add(attr);
4376  }
4377  return attributes;
4378  } catch (SQLException ex) {
4379  throw new TskCoreException("Error getting attributes for artifact, artifact id = " + artifact.getArtifactID(), ex);
4380  } finally {
4381  closeResultSet(rs);
4382  connection.close();
4384  }
4385  }
4386 
4399  public ArrayList<BlackboardAttribute> getMatchingAttributes(String whereClause) throws TskCoreException {
4400  CaseDbConnection connection = connections.getConnection();
4402  Statement s = null;
4403  ResultSet rs = null;
4404  try {
4405  s = connection.createStatement();
4406  rs = connection.executeQuery(s, "SELECT blackboard_attributes.artifact_id AS artifact_id, "
4407  + "blackboard_attributes.source AS source, blackboard_attributes.context AS context, "
4408  + "blackboard_attributes.attribute_type_id AS attribute_type_id, "
4409  + "blackboard_attributes.value_type AS value_type, blackboard_attributes.value_byte AS value_byte, "
4410  + "blackboard_attributes.value_text AS value_text, blackboard_attributes.value_int32 AS value_int32, "
4411  + "blackboard_attributes.value_int64 AS value_int64, blackboard_attributes.value_double AS value_double "
4412  + "FROM blackboard_attributes " + whereClause); //NON-NLS
4413  ArrayList<BlackboardAttribute> matches = new ArrayList<BlackboardAttribute>();
4414  while (rs.next()) {
4416  // attribute type is cached, so this does not necessarily call to the db
4417  type = this.getAttributeType(rs.getInt("attribute_type_id"));
4419  rs.getLong("artifact_id"),
4420  type,
4421  rs.getString("source"),
4422  rs.getString("context"),
4423  rs.getInt("value_int32"),
4424  rs.getLong("value_int64"),
4425  rs.getDouble("value_double"),
4426  rs.getString("value_text"),
4427  rs.getBytes("value_byte"), this
4428  );
4429  matches.add(attr);
4430  }
4431  return matches;
4432  } catch (SQLException ex) {
4433  throw new TskCoreException("Error getting attributes using this where clause: " + whereClause, ex);
4434  } finally {
4435  closeResultSet(rs);
4436  closeStatement(s);
4437  connection.close();
4439  }
4440  }
4441 
4453  public ArrayList<BlackboardArtifact> getMatchingArtifacts(String whereClause) throws TskCoreException {
4454  CaseDbConnection connection = connections.getConnection();
4456  ResultSet rs = null;
4457  Statement s = null;
4458  try {
4459  s = connection.createStatement();
4460  rs = connection.executeQuery(s, "SELECT blackboard_artifacts.artifact_id AS artifact_id, "
4461  + "blackboard_artifacts.obj_id AS obj_id, blackboard_artifacts.artifact_obj_id AS artifact_obj_id, blackboard_artifacts.data_source_obj_id AS data_source_obj_id, blackboard_artifacts.artifact_type_id AS artifact_type_id, "
4462  + "blackboard_artifacts.review_status_id AS review_status_id "
4463  + "FROM blackboard_artifacts " + whereClause); //NON-NLS
4464  ArrayList<BlackboardArtifact> matches = new ArrayList<BlackboardArtifact>();
4465  while (rs.next()) {
4466  BlackboardArtifact.Type type;
4467  // artifact type is cached, so this does not necessarily call to the db
4468  type = this.getArtifactType(rs.getInt("artifact_type_id"));
4469  BlackboardArtifact artifact = new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
4470  type.getTypeID(), type.getTypeName(), type.getDisplayName(),
4471  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")));
4472  matches.add(artifact);
4473  }
4474  return matches;
4475  } catch (SQLException ex) {
4476  throw new TskCoreException("Error getting attributes using this where clause: " + whereClause, ex);
4477  } finally {
4478  closeResultSet(rs);
4479  closeStatement(s);
4480  connection.close();
4482  }
4483  }
4484 
4498  public BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id) throws TskCoreException {
4499  BlackboardArtifact.Type type = getArtifactType(artifactTypeID);
4500  return newBlackboardArtifact(artifactTypeID, obj_id, type.getTypeName(), type.getDisplayName());
4501  }
4502 
4514  public BlackboardArtifact newBlackboardArtifact(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
4515  return newBlackboardArtifact(artifactType.getTypeID(), obj_id, artifactType.getLabel(), artifactType.getDisplayName());
4516  }
4517 
4518  private BlackboardArtifact newBlackboardArtifact(int artifact_type_id, long obj_id, String artifactTypeName, String artifactDisplayName) throws TskCoreException {
4519  CaseDbConnection connection = connections.getConnection();
4521  ResultSet resultSet = null;
4522  try {
4523  long artifact_obj_id = addObject(obj_id, TskData.ObjectType.ARTIFACT.getObjectType(), connection);
4524  long data_source_obj_id = getDataSourceObjectId(connection, obj_id);
4525 
4526  PreparedStatement statement = null;
4527  if (dbType == DbType.POSTGRESQL) {
4528  statement = connection.getPreparedStatement(PREPARED_STATEMENT.POSTGRESQL_INSERT_ARTIFACT, Statement.RETURN_GENERATED_KEYS);
4529  statement.clearParameters();
4530  statement.setLong(1, obj_id);
4531  statement.setLong(2, artifact_obj_id);
4532  statement.setLong(3, data_source_obj_id);
4533  statement.setInt(4, artifact_type_id);
4534 
4535  } else {
4536  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_ARTIFACT, Statement.RETURN_GENERATED_KEYS);
4537  statement.clearParameters();
4538  this.nextArtifactId++;
4539  statement.setLong(1, this.nextArtifactId);
4540  statement.setLong(2, obj_id);
4541  statement.setLong(3, artifact_obj_id);
4542  statement.setLong(4, data_source_obj_id);
4543  statement.setInt(5, artifact_type_id);
4544 
4545  }
4546  connection.executeUpdate(statement);
4547  resultSet = statement.getGeneratedKeys();
4548  resultSet.next();
4549  return new BlackboardArtifact(this, resultSet.getLong(1), //last_insert_rowid()
4550  obj_id, artifact_obj_id, data_source_obj_id, artifact_type_id, artifactTypeName, artifactDisplayName, BlackboardArtifact.ReviewStatus.UNDECIDED, true);
4551  } catch (SQLException ex) {
4552  throw new TskCoreException("Error creating a blackboard artifact", ex);
4553  } finally {
4554  closeResultSet(resultSet);
4555  connection.close();
4557  }
4558  }
4559 
4572  boolean getContentHasChildren(Content content) throws TskCoreException {
4573  CaseDbConnection connection = connections.getConnection();
4575  ResultSet rs = null;
4576  try {
4577  // SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?
4578  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CHILD_OBJECTS_BY_PARENT);
4579  statement.clearParameters();
4580  statement.setLong(1, content.getId());
4581  rs = connection.executeQuery(statement);
4582  boolean hasChildren = false;
4583  if (rs.next()) {
4584  hasChildren = rs.getInt("count") > 0;
4585  }
4586  return hasChildren;
4587  } catch (SQLException e) {
4588  throw new TskCoreException("Error checking for children of parent " + content, e);
4589  } finally {
4590  closeResultSet(rs);
4591  connection.close();
4593  }
4594  }
4595 
4608  int getContentChildrenCount(Content content) throws TskCoreException {
4609 
4610  if (!this.getHasChildren(content)) {
4611  return 0;
4612  }
4613 
4614  CaseDbConnection connection = connections.getConnection();
4616  ResultSet rs = null;
4617  try {
4618  // SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?
4619  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CHILD_OBJECTS_BY_PARENT);
4620  statement.clearParameters();
4621  statement.setLong(1, content.getId());
4622  rs = connection.executeQuery(statement);
4623  int countChildren = -1;
4624  if (rs.next()) {
4625  countChildren = rs.getInt("count");
4626  }
4627  return countChildren;
4628  } catch (SQLException e) {
4629  throw new TskCoreException("Error checking for children of parent " + content, e);
4630  } finally {
4631  closeResultSet(rs);
4632  connection.close();
4634  }
4635  }
4636 
4648  List<Content> getAbstractFileChildren(Content parent, TSK_DB_FILES_TYPE_ENUM type) throws TskCoreException {
4649  CaseDbConnection connection = connections.getConnection();
4651  ResultSet rs = null;
4652  try {
4653  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT_AND_TYPE);
4654  statement.clearParameters();
4655  long parentId = parent.getId();
4656  statement.setLong(1, parentId);
4657  statement.setShort(2, type.getFileType());
4658  rs = connection.executeQuery(statement);
4659  return fileChildren(rs, connection, parentId);
4660  } catch (SQLException ex) {
4661  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4662  } finally {
4663  closeResultSet(rs);
4664  connection.close();
4666  }
4667  }
4668 
4678  List<Content> getAbstractFileChildren(Content parent) throws TskCoreException {
4679  CaseDbConnection connection = connections.getConnection();
4681  ResultSet rs = null;
4682  try {
4683  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT);
4684  statement.clearParameters();
4685  long parentId = parent.getId();
4686  statement.setLong(1, parentId);
4687  rs = connection.executeQuery(statement);
4688  return fileChildren(rs, connection, parentId);
4689  } catch (SQLException ex) {
4690  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4691  } finally {
4692  closeResultSet(rs);
4693  connection.close();
4695  }
4696  }
4697 
4709  List<Long> getAbstractFileChildrenIds(Content parent, TSK_DB_FILES_TYPE_ENUM type) throws TskCoreException {
4710  CaseDbConnection connection = connections.getConnection();
4712  ResultSet rs = null;
4713  try {
4714  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_IDS_BY_PARENT_AND_TYPE);
4715  statement.clearParameters();
4716  statement.setLong(1, parent.getId());
4717  statement.setShort(2, type.getFileType());
4718  rs = connection.executeQuery(statement);
4719  List<Long> children = new ArrayList<Long>();
4720  while (rs.next()) {
4721  children.add(rs.getLong("obj_id"));
4722  }
4723  return children;
4724  } catch (SQLException ex) {
4725  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4726  } finally {
4727  closeResultSet(rs);
4728  connection.close();
4730  }
4731  }
4732 
4742  List<Long> getAbstractFileChildrenIds(Content parent) throws TskCoreException {
4743  CaseDbConnection connection = connections.getConnection();
4745  ResultSet rs = null;
4746  try {
4747  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_IDS_BY_PARENT);
4748  statement.clearParameters();
4749  statement.setLong(1, parent.getId());
4750  rs = connection.executeQuery(statement);
4751  List<Long> children = new ArrayList<Long>();
4752  while (rs.next()) {
4753  children.add(rs.getLong("obj_id"));
4754  }
4755  return children;
4756  } catch (SQLException ex) {
4757  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4758  } finally {
4759  closeResultSet(rs);
4760  connection.close();
4762  }
4763  }
4764 
4775  List<Long> getBlackboardArtifactChildrenIds(Content parent) throws TskCoreException {
4776  CaseDbConnection connection = connections.getConnection();
4778  ResultSet rs = null;
4779  try {
4780  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_OBJECTIDS_BY_PARENT);
4781  statement.clearParameters();
4782  statement.setLong(1, parent.getId());
4783  rs = connection.executeQuery(statement);
4784  List<Long> children = new ArrayList<Long>();
4785  while (rs.next()) {
4786  children.add(rs.getLong("obj_id"));
4787  }
4788  return children;
4789  } catch (SQLException ex) {
4790  throw new TskCoreException("Error getting children for BlackboardArtifact", ex);
4791  } finally {
4792  closeResultSet(rs);
4793  connection.close();
4795  }
4796  }
4797 
4807  List<Content> getBlackboardArtifactChildren(Content parent) throws TskCoreException {
4808 
4809  long parentId = parent.getId();
4810  ArrayList<BlackboardArtifact> artsArray = getArtifactsHelper("blackboard_artifacts.obj_id = " + parentId + ";");
4811 
4812  List<Content> lc = new ArrayList<Content>();
4813  lc.addAll(artsArray);
4814  return lc;
4815  }
4816 
4825  Collection<ObjectInfo> getChildrenInfo(Content c) throws TskCoreException {
4826  CaseDbConnection connection = connections.getConnection();
4828  Statement s = null;
4829  ResultSet rs = null;
4830  try {
4831  s = connection.createStatement();
4832  rs = connection.executeQuery(s, "SELECT tsk_objects.obj_id AS obj_id, tsk_objects.type AS type " //NON-NLS
4833  + "FROM tsk_objects LEFT JOIN tsk_files " //NON-NLS
4834  + "ON tsk_objects.obj_id = tsk_files.obj_id " //NON-NLS
4835  + "WHERE tsk_objects.par_obj_id = " + c.getId()
4836  + " ORDER BY tsk_objects.obj_id"); //NON-NLS
4837  Collection<ObjectInfo> infos = new ArrayList<ObjectInfo>();
4838  while (rs.next()) {
4839  infos.add(new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")))); //NON-NLS
4840  }
4841  return infos;
4842  } catch (SQLException ex) {
4843  throw new TskCoreException("Error getting Children Info for Content", ex);
4844  } finally {
4845  closeResultSet(rs);
4846  closeStatement(s);
4847  connection.close();
4849  }
4850  }
4851 
4862  ObjectInfo getParentInfo(Content c) throws TskCoreException {
4863  return getParentInfo(c.getId());
4864  }
4865 
4876  ObjectInfo getParentInfo(long contentId) throws TskCoreException {
4877  CaseDbConnection connection = connections.getConnection();
4879  Statement s = null;
4880  ResultSet rs = null;
4881  try {
4882  s = connection.createStatement();
4883  rs = connection.executeQuery(s, "SELECT parent.obj_id AS obj_id, parent.type AS type " //NON-NLS
4884  + "FROM tsk_objects AS parent INNER JOIN tsk_objects AS child " //NON-NLS
4885  + "ON child.par_obj_id = parent.obj_id " //NON-NLS
4886  + "WHERE child.obj_id = " + contentId); //NON-NLS
4887  if (rs.next()) {
4888  return new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")));
4889  } else {
4890  return null;
4891  }
4892  } catch (SQLException ex) {
4893  throw new TskCoreException("Error getting Parent Info for Content: " + contentId, ex);
4894  } finally {
4895  closeResultSet(rs);
4896  closeStatement(s);
4897  connection.close();
4899  }
4900  }
4901 
4912  Directory getParentDirectory(FsContent fsc) throws TskCoreException {
4913  if (fsc.isRoot()) {
4914  // Given FsContent is a root object and can't have parent directory
4915  return null;
4916  } else {
4917  ObjectInfo parentInfo = getParentInfo(fsc);
4918  if (parentInfo == null) {
4919  return null;
4920  }
4921  Directory parent = null;
4922  if (parentInfo.type == ObjectType.ABSTRACTFILE) {
4923  parent = getDirectoryById(parentInfo.id, fsc.getFileSystem());
4924  } else {
4925  throw new TskCoreException("Parent of FsContent (id: " + fsc.getId() + ") has wrong type to be directory: " + parentInfo.type);
4926  }
4927  return parent;
4928  }
4929  }
4930 
4942  public Content getContentById(long id) throws TskCoreException {
4943  // First check to see if this exists in our frequently used content cache.
4944  Content content = frequentlyUsedContentMap.get(id);
4945  if (null != content) {
4946  return content;
4947  }
4948 
4949  CaseDbConnection connection = connections.getConnection();
4951  Statement s = null;
4952  ResultSet rs = null;
4953  long parentId;
4954  TskData.ObjectType type;
4955 
4956  try {
4957  s = connection.createStatement();
4958  rs = connection.executeQuery(s, "SELECT * FROM tsk_objects WHERE obj_id = " + id + " LIMIT 1"); //NON-NLS
4959  if (!rs.next()) {
4960  return null;
4961  }
4962  parentId = rs.getLong("par_obj_id"); //NON-NLS
4963  type = TskData.ObjectType.valueOf(rs.getShort("type")); //NON-NLS
4964  } catch (SQLException ex) {
4965  throw new TskCoreException("Error getting Content by ID.", ex);
4966  } finally {
4967  closeResultSet(rs);
4968  closeStatement(s);
4969  connection.close();
4971  }
4972 
4973  // Construct the object
4974  switch (type) {
4975  case IMG:
4976  content = getImageById(id);
4977  frequentlyUsedContentMap.put(id, content);
4978  break;
4979  case VS:
4980  content = getVolumeSystemById(id, parentId);
4981  break;
4982  case VOL:
4983  content = getVolumeById(id, parentId);
4984  frequentlyUsedContentMap.put(id, content);
4985  break;
4986  case POOL:
4987  content = getPoolById(id, parentId);
4988  break;
4989  case FS:
4990  content = getFileSystemById(id, parentId);
4991  frequentlyUsedContentMap.put(id, content);
4992  break;
4993  case ABSTRACTFILE:
4994  content = getAbstractFileById(id);
4995 
4996  // Add virtual and root directories to frequently used map.
4997  // Calling isRoot() on local directories goes up the entire directory structure
4998  // and they can only be the root of portable cases, so skip trying to add
4999  // them to the cache.
5000  if (((AbstractFile) content).isVirtual()
5001  || ((!(content instanceof LocalDirectory)) && ((AbstractFile) content).isRoot())) {
5002  frequentlyUsedContentMap.put(id, content);
5003  }
5004  break;
5005  case ARTIFACT:
5006  content = getArtifactById(id);
5007  break;
5008  case REPORT:
5009  content = getReportById(id);
5010  break;
5011  default:
5012  throw new TskCoreException("Could not obtain Content object with ID: " + id);
5013  }
5014 
5015  return content;
5016  }
5017 
5025  String getFilePath(long id) {
5026  CaseDbConnection connection;
5027  try {
5028  connection = connections.getConnection();
5029  } catch (TskCoreException ex) {
5030  logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
5031  return null;
5032  }
5033  String filePath = null;
5035  ResultSet rs = null;
5036  try {
5037  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_FOR_FILE);
5038  statement.clearParameters();
5039  statement.setLong(1, id);
5040  rs = connection.executeQuery(statement);
5041  if (rs.next()) {
5042  filePath = rs.getString("path");
5043  }
5044  } catch (SQLException ex) {
5045  logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
5046  } finally {
5047  closeResultSet(rs);
5048  connection.close();
5050  }
5051  return filePath;
5052  }
5053 
5061  TskData.EncodingType getEncodingType(long id) {
5062  CaseDbConnection connection;
5063  try {
5064  connection = connections.getConnection();
5065  } catch (TskCoreException ex) {
5066  logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
5067  return null;
5068  }
5069  TskData.EncodingType type = TskData.EncodingType.NONE;
5071  ResultSet rs = null;
5072  try {
5073  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ENCODING_FOR_FILE);
5074  statement.clearParameters();
5075  statement.setLong(1, id);
5076  rs = connection.executeQuery(statement);
5077  if (rs.next()) {
5078  type = TskData.EncodingType.valueOf(rs.getInt(1));
5079  }
5080  } catch (SQLException ex) {
5081  logger.log(Level.SEVERE, "Error getting encoding type for file " + id, ex); //NON-NLS
5082  } finally {
5083  closeResultSet(rs);
5084  connection.close();
5086  }
5087  return type;
5088  }
5089 
5098  String getFileParentPath(long objectId, CaseDbConnection connection) {
5099  String parentPath = null;
5101  ResultSet rs = null;
5102  try {
5103  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_PATH_FOR_FILE);
5104  statement.clearParameters();
5105  statement.setLong(1, objectId);
5106  rs = connection.executeQuery(statement);
5107  if (rs.next()) {
5108  parentPath = rs.getString("parent_path");
5109  }
5110  } catch (SQLException ex) {
5111  logger.log(Level.SEVERE, "Error getting file parent_path for file " + objectId, ex); //NON-NLS
5112  } finally {
5113  closeResultSet(rs);
5115  }
5116  return parentPath;
5117  }
5118 
5127  String getFileName(long objectId, CaseDbConnection connection) {
5128  String fileName = null;
5130  ResultSet rs = null;
5131  try {
5132  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_NAME);
5133  statement.clearParameters();
5134  statement.setLong(1, objectId);
5135  rs = connection.executeQuery(statement);
5136  if (rs.next()) {
5137  fileName = rs.getString("name");
5138  }
5139  } catch (SQLException ex) {
5140  logger.log(Level.SEVERE, "Error getting file parent_path for file " + objectId, ex); //NON-NLS
5141  } finally {
5142  closeResultSet(rs);
5144  }
5145  return fileName;
5146  }
5147 
5158  DerivedFile.DerivedMethod getDerivedMethod(long id) throws TskCoreException {
5159  CaseDbConnection connection = connections.getConnection();
5160  DerivedFile.DerivedMethod method = null;
5162  ResultSet rs1 = null;
5163  ResultSet rs2 = null;
5164  try {
5165  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_DERIVED_FILE);
5166  statement.clearParameters();
5167  statement.setLong(1, id);
5168  rs1 = connection.executeQuery(statement);
5169  if (rs1.next()) {
5170  int method_id = rs1.getInt("derived_id");
5171  String rederive = rs1.getString("rederive");
5172  method = new DerivedFile.DerivedMethod(method_id, rederive);
5173  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_DERIVATION_METHOD);
5174  statement.clearParameters();
5175  statement.setInt(1, method_id);
5176  rs2 = connection.executeQuery(statement);
5177  if (rs2.next()) {
5178  method.setToolName(rs2.getString("tool_name"));
5179  method.setToolVersion(rs2.getString("tool_version"));
5180  method.setOther(rs2.getString("other"));
5181  }
5182  }
5183  } catch (SQLException e) {
5184  logger.log(Level.SEVERE, "Error getting derived method for file: " + id, e); //NON-NLS
5185  } finally {
5186  closeResultSet(rs2);
5187  closeResultSet(rs1);
5188  connection.close();
5190  }
5191  return method;
5192  }
5193 
5204  public AbstractFile getAbstractFileById(long id) throws TskCoreException {
5205  CaseDbConnection connection = connections.getConnection();
5206  try {
5207  return getAbstractFileById(id, connection);
5208  } finally {
5209  connection.close();
5210  }
5211  }
5212 
5225  AbstractFile getAbstractFileById(long objectId, CaseDbConnection connection) throws TskCoreException {
5227  ResultSet rs = null;
5228  try {
5229  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_BY_ID);
5230  statement.clearParameters();
5231  statement.setLong(1, objectId);
5232  rs = connection.executeQuery(statement);
5233  List<AbstractFile> files = resultSetToAbstractFiles(rs, connection);
5234  if (files.size() > 0) {
5235  return files.get(0);
5236  } else {
5237  return null;
5238  }
5239  } catch (SQLException ex) {
5240  throw new TskCoreException("Error getting file by id, id = " + objectId, ex);
5241  } finally {
5242  closeResultSet(rs);
5244  }
5245  }
5246 
5257  public BlackboardArtifact getArtifactById(long id) throws TskCoreException {
5258  CaseDbConnection connection = connections.getConnection();
5260  ResultSet rs = null;
5261  try {
5262  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_BY_ARTIFACT_OBJ_ID);
5263  statement.clearParameters();
5264  statement.setLong(1, id);
5265  rs = connection.executeQuery(statement);
5266  List<BlackboardArtifact> artifacts = resultSetToArtifacts(rs);
5267  if (artifacts.size() > 0) {
5268  return artifacts.get(0);
5269  } else {
5270  return null;
5271  }
5272  } catch (SQLException ex) {
5273  throw new TskCoreException("Error getting artifacts by artifact_obj_id, artifact_obj_id = " + id, ex);
5274  } finally {
5275  closeResultSet(rs);
5276  connection.close();
5278  }
5279  }
5280 
5291  public BlackboardArtifact getArtifactByArtifactId(long id) throws TskCoreException {
5292  CaseDbConnection connection = connections.getConnection();
5294  ResultSet rs = null;
5295  try {
5296  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_BY_ARTIFACT_ID);
5297  statement.clearParameters();
5298  statement.setLong(1, id);
5299  rs = connection.executeQuery(statement);
5300  List<BlackboardArtifact> artifacts = resultSetToArtifacts(rs);
5301  if (artifacts.size() > 0) {
5302  return artifacts.get(0);
5303  } else {
5304  return null;
5305  }
5306  } catch (SQLException ex) {
5307  throw new TskCoreException("Error getting artifacts by artifact id, artifact id = " + id, ex);
5308  } finally {
5309  closeResultSet(rs);
5310  connection.close();
5312  }
5313  }
5314 
5327  private long getFileSystemId(long fileId, CaseDbConnection connection) {
5329  ResultSet rs = null;
5330  long ret = -1;
5331  try {
5332  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_SYSTEM_BY_OBJECT);
5333  statement.clearParameters();
5334  statement.setLong(1, fileId);
5335  rs = connection.executeQuery(statement);
5336  if (rs.next()) {
5337  ret = rs.getLong("fs_obj_id");
5338  if (ret == 0) {
5339  ret = -1;
5340  }
5341  }
5342  } catch (SQLException e) {
5343  logger.log(Level.SEVERE, "Error checking file system id of a file, id = " + fileId, e); //NON-NLS
5344  } finally {
5345  closeResultSet(rs);
5347  }
5348  return ret;
5349  }
5350 
5362  public boolean isFileFromSource(Content dataSource, long fileId) throws TskCoreException {
5363  String query = String.format("SELECT COUNT(*) AS count FROM tsk_files WHERE obj_id = %d AND data_source_obj_id = %d", fileId, dataSource.getId()); //NON-NLS
5364  CaseDbConnection connection = connections.getConnection();
5366  Statement statement = null;
5367  ResultSet resultSet = null;
5368  try {
5369  statement = connection.createStatement();
5370  resultSet = connection.executeQuery(statement, query);
5371  resultSet.next();
5372  return (resultSet.getLong("count") > 0L);
5373  } catch (SQLException ex) {
5374  throw new TskCoreException(String.format("Error executing query %s", query), ex);
5375  } finally {
5376  closeResultSet(resultSet);
5377  closeStatement(statement);
5378  connection.close();
5380  }
5381  }
5382 
5394  public List<AbstractFile> findFiles(Content dataSource, String fileName) throws TskCoreException {
5395  List<AbstractFile> files = new ArrayList<AbstractFile>();
5396  CaseDbConnection connection = connections.getConnection();
5398  ResultSet resultSet = null;
5399  try {
5400  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_DATA_SOURCE_AND_NAME);
5401  statement.clearParameters();
5402  statement.setString(1, fileName.toLowerCase());
5403  statement.setLong(2, dataSource.getId());
5404  resultSet = connection.executeQuery(statement);
5405  files.addAll(resultSetToAbstractFiles(resultSet, connection));
5406  } catch (SQLException e) {
5407  throw new TskCoreException(bundle.getString("SleuthkitCase.findFiles.exception.msg3.text"), e);
5408  } finally {
5409  closeResultSet(resultSet);
5410  connection.close();
5412  }
5413  return files;
5414  }
5415 
5429  public List<AbstractFile> findFiles(Content dataSource, String fileName, String dirSubString) throws TskCoreException {
5430  List<AbstractFile> files = new ArrayList<AbstractFile>();
5431  CaseDbConnection connection = connections.getConnection();
5433  ResultSet resultSet = null;
5434  try {
5435  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_DATA_SOURCE_AND_PARENT_PATH_AND_NAME);
5436  statement.clearParameters();
5437  statement.setString(1, fileName.toLowerCase());
5438  statement.setString(2, "%" + dirSubString.toLowerCase() + "%"); //NON-NLS
5439  statement.setLong(3, dataSource.getId());
5440  resultSet = connection.executeQuery(statement);
5441  files.addAll(resultSetToAbstractFiles(resultSet, connection));
5442  } catch (SQLException e) {
5443  throw new TskCoreException(bundle.getString("SleuthkitCase.findFiles3.exception.msg3.text"), e);
5444  } finally {
5445  closeResultSet(resultSet);
5446  connection.close();
5448  }
5449  return files;
5450  }
5451 
5463  public VirtualDirectory addVirtualDirectory(long parentId, String directoryName) throws TskCoreException {
5464  CaseDbTransaction localTrans = beginTransaction();
5465  try {
5466  VirtualDirectory newVD = addVirtualDirectory(parentId, directoryName, localTrans);
5467  localTrans.commit();
5468  localTrans = null;
5469  return newVD;
5470  } finally {
5471  if (null != localTrans) {
5472  try {
5473  localTrans.rollback();
5474  } catch (TskCoreException ex2) {
5475  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
5476  }
5477  }
5478  }
5479  }
5480 
5493  private long addObject(long parentId, int objectType, CaseDbConnection connection) throws SQLException {
5494  ResultSet resultSet = null;
5496  try {
5497  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
5498  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OBJECT, Statement.RETURN_GENERATED_KEYS);
5499  statement.clearParameters();
5500  if (parentId != 0) {
5501  statement.setLong(1, parentId);
5502  } else {
5503  statement.setNull(1, java.sql.Types.BIGINT);
5504  }
5505  statement.setInt(2, objectType);
5506  connection.executeUpdate(statement);
5507  resultSet = statement.getGeneratedKeys();
5508 
5509  if (resultSet.next()) {
5510  if (parentId != 0) {
5511  setHasChildren(parentId);
5512  }
5513  return resultSet.getLong(1); //last_insert_rowid()
5514  } else {
5515  throw new SQLException("Error inserting object with parent " + parentId + " into tsk_objects");
5516  }
5517  } finally {
5518  closeResultSet(resultSet);
5520  }
5521  }
5522 
5540  public VirtualDirectory addVirtualDirectory(long parentId, String directoryName, CaseDbTransaction transaction) throws TskCoreException {
5541  if (transaction == null) {
5542  throw new TskCoreException("Passed null CaseDbTransaction");
5543  }
5544 
5545  ResultSet resultSet = null;
5546  try {
5547  // Get the parent path.
5548  CaseDbConnection connection = transaction.getConnection();
5549 
5550  String parentPath;
5551  Content parent = this.getAbstractFileById(parentId, connection);
5552  if (parent instanceof AbstractFile) {
5553  if (isRootDirectory((AbstractFile) parent, transaction)) {
5554  parentPath = "/";
5555  } else {
5556  parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + "/"; //NON-NLS
5557  }
5558  } else {
5559  // The parent was either null or not an abstract file
5560  parentPath = "/";
5561  }
5562 
5563  // Insert a row for the virtual directory into the tsk_objects table.
5564  long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
5565 
5566  // Insert a row for the virtual directory into the tsk_files table.
5567  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
5568  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id,extension)
5569  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
5570  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
5571  statement.clearParameters();
5572  statement.setLong(1, newObjId);
5573 
5574  // If the parent is part of a file system, grab its file system ID
5575  if (0 != parentId) {
5576  long parentFs = this.getFileSystemId(parentId, connection);
5577  if (parentFs != -1) {
5578  statement.setLong(2, parentFs);
5579  } else {
5580  statement.setNull(2, java.sql.Types.BIGINT);
5581  }
5582  } else {
5583  statement.setNull(2, java.sql.Types.BIGINT);
5584  }
5585 
5586  // name
5587  statement.setString(3, directoryName);
5588 
5589  //type
5590  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType());
5591  statement.setShort(5, (short) 1);
5592 
5593  //flags
5595  statement.setShort(6, dirType.getValue());
5597  statement.setShort(7, metaType.getValue());
5598 
5599  //allocated
5601  statement.setShort(8, dirFlag.getValue());
5602  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
5603  | TSK_FS_META_FLAG_ENUM.USED.getValue());
5604  statement.setShort(9, metaFlags);
5605 
5606  //size
5607  statement.setLong(10, 0);
5608 
5609  // nulls for params 11-14
5610  statement.setNull(11, java.sql.Types.BIGINT);
5611  statement.setNull(12, java.sql.Types.BIGINT);
5612  statement.setNull(13, java.sql.Types.BIGINT);
5613  statement.setNull(14, java.sql.Types.BIGINT);
5614 
5615  statement.setNull(15, java.sql.Types.VARCHAR); // MD5
5616  statement.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
5617  statement.setNull(17, java.sql.Types.VARCHAR); // MIME type
5618 
5619  // parent path
5620  statement.setString(18, parentPath);
5621 
5622  // data source object id (same as object id if this is a data source)
5623  long dataSourceObjectId;
5624  if (0 == parentId) {
5625  dataSourceObjectId = newObjId;
5626  } else {
5627  dataSourceObjectId = getDataSourceObjectId(connection, parentId);
5628  }
5629  statement.setLong(19, dataSourceObjectId);
5630 
5631  //extension, since this is not really file we just set it to null
5632  statement.setString(20, null);
5633  connection.executeUpdate(statement);
5634 
5635  return new VirtualDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType,
5636  metaType, dirFlag, metaFlags, null, FileKnown.UNKNOWN,
5637  parentPath);
5638  } catch (SQLException e) {
5639  throw new TskCoreException("Error creating virtual directory '" + directoryName + "'", e);
5640  } finally {
5641  closeResultSet(resultSet);
5642  }
5643  }
5644 
5657  public LocalDirectory addLocalDirectory(long parentId, String directoryName) throws TskCoreException {
5658  CaseDbTransaction localTrans = beginTransaction();
5659  try {
5660  LocalDirectory newLD = addLocalDirectory(parentId, directoryName, localTrans);
5661  localTrans.commit();
5662  return newLD;
5663  } catch (TskCoreException ex) {
5664  try {
5665  localTrans.rollback();
5666  } catch (TskCoreException ex2) {
5667  logger.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
5668  }
5669  throw ex;
5670  }
5671  }
5672 
5690  public LocalDirectory addLocalDirectory(long parentId, String directoryName, CaseDbTransaction transaction) throws TskCoreException {
5691  if (transaction == null) {
5692  throw new TskCoreException("Passed null CaseDbTransaction");
5693  }
5694 
5695  ResultSet resultSet = null;
5696  try {
5697  // Get the parent path.
5698  CaseDbConnection connection = transaction.getConnection();
5699  AbstractFile parent = getAbstractFileById(parentId, connection);
5700  String parentPath;
5701  if ((parent == null) || isRootDirectory(parent, transaction)) {
5702  parentPath = "/";
5703  } else {
5704  parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS
5705  }
5706 
5707  // Insert a row for the local directory into the tsk_objects table.
5708  long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
5709 
5710  // Insert a row for the local directory into the tsk_files table.
5711  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
5712  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id)
5713  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
5714  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
5715  statement.clearParameters();
5716  statement.setLong(1, newObjId);
5717 
5718  // The parent of a local directory will never be a file system
5719  statement.setNull(2, java.sql.Types.BIGINT);
5720 
5721  // name
5722  statement.setString(3, directoryName);
5723 
5724  //type
5725  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR.getFileType());
5726  statement.setShort(5, (short) 1);
5727 
5728  //flags
5730  statement.setShort(6, dirType.getValue());
5732  statement.setShort(7, metaType.getValue());
5733 
5734  //allocated
5736  statement.setShort(8, dirFlag.getValue());
5737  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
5738  | TSK_FS_META_FLAG_ENUM.USED.getValue());
5739  statement.setShort(9, metaFlags);
5740 
5741  //size
5742  statement.setLong(10, 0);
5743 
5744  // nulls for params 11-14
5745  statement.setNull(11, java.sql.Types.BIGINT);
5746  statement.setNull(12, java.sql.Types.BIGINT);
5747  statement.setNull(13, java.sql.Types.BIGINT);
5748  statement.setNull(14, java.sql.Types.BIGINT);
5749 
5750  statement.setNull(15, java.sql.Types.VARCHAR); // MD5
5751  statement.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
5752  statement.setNull(17, java.sql.Types.VARCHAR); // MIME type
5753 
5754  // parent path
5755  statement.setString(18, parentPath);
5756 
5757  // data source object id
5758  long dataSourceObjectId = getDataSourceObjectId(connection, parentId);
5759  statement.setLong(19, dataSourceObjectId);
5760 
5761  //extension, since this is a directory we just set it to null
5762  statement.setString(20, null);
5763 
5764  connection.executeUpdate(statement);
5765 
5766  return new LocalDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType,
5767  metaType, dirFlag, metaFlags, null, FileKnown.UNKNOWN,
5768  parentPath);
5769  } catch (SQLException e) {
5770  throw new TskCoreException("Error creating local directory '" + directoryName + "'", e);
5771  } finally {
5772  closeResultSet(resultSet);
5773  }
5774  }
5775 
5795  public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, CaseDbTransaction transaction) throws TskCoreException {
5797  Statement statement = null;
5798  try {
5799  // Insert a row for the root virtual directory of the data source
5800  // into the tsk_objects table.
5801  CaseDbConnection connection = transaction.getConnection();
5802  long newObjId = addObject(0, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
5803 
5804  // Insert a row for the virtual directory of the data source into
5805  // the data_source_info table.
5806  statement = connection.createStatement();
5807  statement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) "
5808  + "VALUES(" + newObjId + ", '" + deviceId + "', '" + timeZone + "');");
5809 
5810  // Insert a row for the root virtual directory of the data source
5811  // into the tsk_files table. Note that its data source object id is
5812  // its own object id.
5813  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path,
5814  // dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime,
5815  // atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id, extension)
5816  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
5817  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
5818  preparedStatement.clearParameters();
5819  preparedStatement.setLong(1, newObjId);
5820  preparedStatement.setNull(2, java.sql.Types.BIGINT);
5821  preparedStatement.setString(3, rootDirectoryName);
5822  preparedStatement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType());
5823  preparedStatement.setShort(5, (short) 1);
5825  preparedStatement.setShort(6, TSK_FS_NAME_TYPE_ENUM.DIR.getValue());
5827  preparedStatement.setShort(7, metaType.getValue());
5829  preparedStatement.setShort(8, dirFlag.getValue());
5830  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
5831  | TSK_FS_META_FLAG_ENUM.USED.getValue());
5832  preparedStatement.setShort(9, metaFlags);
5833  preparedStatement.setLong(10, 0);
5834  preparedStatement.setNull(11, java.sql.Types.BIGINT);
5835  preparedStatement.setNull(12, java.sql.Types.BIGINT);
5836  preparedStatement.setNull(13, java.sql.Types.BIGINT);
5837  preparedStatement.setNull(14, java.sql.Types.BIGINT);
5838  preparedStatement.setNull(15, java.sql.Types.VARCHAR); // MD5
5839  preparedStatement.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
5840  preparedStatement.setNull(17, java.sql.Types.VARCHAR); // MIME type
5841  String parentPath = "/"; //NON-NLS
5842  preparedStatement.setString(18, parentPath);
5843  preparedStatement.setLong(19, newObjId);
5844  preparedStatement.setString(20, null); //extension, just set it to null
5845  connection.executeUpdate(preparedStatement);
5846 
5847  return new LocalFilesDataSource(this, newObjId, newObjId, deviceId, rootDirectoryName, dirType, metaType, dirFlag, metaFlags, timeZone, null, FileKnown.UNKNOWN, parentPath);
5848 
5849  } catch (SQLException ex) {
5850  throw new TskCoreException(String.format("Error creating local files data source with device id %s and directory name %s", deviceId, rootDirectoryName), ex);
5851  } finally {
5852  closeStatement(statement);
5854  }
5855  }
5856 
5876  public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths,
5877  String timezone, String md5, String sha1, String sha256,
5878  String deviceId,
5879  CaseDbTransaction transaction) throws TskCoreException {
5881  Statement statement = null;
5882  try {
5883  // Insert a row for the Image into the tsk_objects table.
5884  CaseDbConnection connection = transaction.getConnection();
5885  long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
5886 
5887  // Add a row to tsk_image_info
5888  // INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
5889  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO);
5890  preparedStatement.clearParameters();
5891  preparedStatement.setLong(1, newObjId);
5892  preparedStatement.setShort(2, (short) type.getValue());
5893  preparedStatement.setLong(3, sectorSize);
5894  preparedStatement.setString(4, timezone);
5895  //prevent negative size
5896  long savedSize = size < 0 ? 0 : size;
5897  preparedStatement.setLong(5, savedSize);
5898  preparedStatement.setString(6, md5);
5899  preparedStatement.setString(7, sha1);
5900  preparedStatement.setString(8, sha256);
5901  preparedStatement.setString(9, displayName);
5902  connection.executeUpdate(preparedStatement);
5903 
5904  // If there are paths, add them to tsk_image_names
5905  for (int i = 0; i < imagePaths.size(); i++) {
5906  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
5907  preparedStatement.clearParameters();
5908  preparedStatement.setLong(1, newObjId);
5909  preparedStatement.setString(2, imagePaths.get(i));
5910  preparedStatement.setLong(3, i);
5911  connection.executeUpdate(preparedStatement);
5912  }
5913 
5914  // Add a row to data_source_info
5915  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DATA_SOURCE_INFO);
5916  statement = connection.createStatement();
5917  preparedStatement.setLong(1, newObjId);
5918  preparedStatement.setString(2, deviceId);
5919  preparedStatement.setString(3, timezone);
5920  connection.executeUpdate(preparedStatement);
5921 
5922  // Create the new Image object
5923  String name = displayName;
5924  if (name == null || name.isEmpty()) {
5925  if (imagePaths.size() > 0) {
5926  String path = imagePaths.get(0);
5927  name = (new java.io.File(path)).getName();
5928  } else {
5929  name = "";
5930  }
5931  }
5932  return new Image(this, newObjId, type.getValue(), deviceId, sectorSize, name,
5933  imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, savedSize);
5934  } catch (SQLException ex) {
5935  if (!imagePaths.isEmpty()) {
5936  throw new TskCoreException(String.format("Error adding image with path %s to database", imagePaths.get(0)), ex);
5937  } else {
5938  throw new TskCoreException(String.format("Error adding image with display name %s to database", displayName), ex);
5939  }
5940  } finally {
5941  closeStatement(statement);
5943  }
5944  }
5945 
5959  public VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset,
5960  long blockSize, CaseDbTransaction transaction) throws TskCoreException {
5962  try {
5963  // Insert a row for the VolumeSystem into the tsk_objects table.
5964  CaseDbConnection connection = transaction.getConnection();
5965  long newObjId = addObject(parentObjId, TskData.ObjectType.VS.getObjectType(), connection);
5966 
5967  // Add a row to tsk_vs_info
5968  // INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size)
5969  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_INFO);
5970  preparedStatement.clearParameters();
5971  preparedStatement.setLong(1, newObjId);
5972  preparedStatement.setShort(2, (short) type.getVsType());
5973  preparedStatement.setLong(3, imgOffset);
5974  preparedStatement.setLong(4, blockSize);
5975  connection.executeUpdate(preparedStatement);
5976 
5977  // Create the new VolumeSystem object
5978  return new VolumeSystem(this, newObjId, "", type.getVsType(), imgOffset, blockSize);
5979  } catch (SQLException ex) {
5980  throw new TskCoreException(String.format("Error creating volume system with parent ID %d and image offset %d",
5981  parentObjId, imgOffset), ex);
5982  } finally {
5984  }
5985  }
5986 
6002  public Volume addVolume(long parentObjId, long addr, long start, long length, String desc,
6003  long flags, CaseDbTransaction transaction) throws TskCoreException {
6005  Statement statement = null;
6006  try {
6007  // Insert a row for the Volume into the tsk_objects table.
6008  CaseDbConnection connection = transaction.getConnection();
6009  long newObjId = addObject(parentObjId, TskData.ObjectType.VOL.getObjectType(), connection);
6010 
6011  // Add a row to tsk_vs_parts
6012  // INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags)
6013  PreparedStatement preparedStatement;
6014  if (this.dbType == DbType.POSTGRESQL) {
6015  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_POSTGRESQL);
6016  } else {
6017  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_SQLITE);
6018  }
6019  preparedStatement.clearParameters();
6020  preparedStatement.setLong(1, newObjId);
6021  preparedStatement.setLong(2, addr);
6022  preparedStatement.setLong(3, start);
6023  preparedStatement.setLong(4, length);
6024  preparedStatement.setString(5, desc);
6025  preparedStatement.setShort(6, (short) flags);
6026  connection.executeUpdate(preparedStatement);
6027 
6028  // Create the new Volume object
6029  return new Volume(this, newObjId, addr, start, length, flags, desc);
6030  } catch (SQLException ex) {
6031  throw new TskCoreException(String.format("Error creating volume with address %d and parent ID %d", addr, parentObjId), ex);
6032  } finally {
6033  closeStatement(statement);
6035  }
6036  }
6037 
6049  public Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTransaction transaction) throws TskCoreException {
6051  Statement statement = null;
6052  try {
6053  // Insert a row for the Pool into the tsk_objects table.
6054  CaseDbConnection connection = transaction.getConnection();
6055  long newObjId = addObject(parentObjId, TskData.ObjectType.POOL.getObjectType(), connection);
6056 
6057  // Add a row to tsk_pool_info
6058  // INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)
6059  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_POOL_INFO);
6060  preparedStatement.clearParameters();
6061  preparedStatement.setLong(1, newObjId);
6062  preparedStatement.setShort(2, type.getValue());
6063  connection.executeUpdate(preparedStatement);
6064 
6065  // Create the new Pool object
6066  return new Pool(this, newObjId, type.getName(), type.getValue());
6067  } catch (SQLException ex) {
6068  throw new TskCoreException(String.format("Error creating pool with type %d and parent ID %d", type.getValue(), parentObjId), ex);
6069  } finally {
6070  closeStatement(statement);
6072  }
6073  }
6074 
6093  public FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS_TYPE_ENUM type, long blockSize, long blockCount,
6094  long rootInum, long firstInum, long lastInum, String displayName,
6095  CaseDbTransaction transaction) throws TskCoreException {
6097  Statement statement = null;
6098  try {
6099  // Insert a row for the FileSystem into the tsk_objects table.
6100  CaseDbConnection connection = transaction.getConnection();
6101  long newObjId = addObject(parentObjId, TskData.ObjectType.FS.getObjectType(), connection);
6102 
6103  // Get the data source object ID
6104  long dataSourceId = getDataSourceObjectId(connection, newObjId);
6105 
6106  // Add a row to tsk_fs_info
6107  // INSERT INTO tsk_fs_info (obj_id, data_source_obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)
6108  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FS_INFO);
6109  preparedStatement.clearParameters();
6110  preparedStatement.setLong(1, newObjId);
6111  preparedStatement.setLong(2, dataSourceId);
6112  preparedStatement.setLong(3, imgOffset);
6113  preparedStatement.setInt(4, type.getValue());
6114  preparedStatement.setLong(5, blockSize);
6115  preparedStatement.setLong(6, blockCount);
6116  preparedStatement.setLong(7, rootInum);
6117  preparedStatement.setLong(8, firstInum);
6118  preparedStatement.setLong(9, lastInum);
6119  preparedStatement.setString(10, displayName);
6120  connection.executeUpdate(preparedStatement);
6121 
6122  // Create the new FileSystem object
6123  return new FileSystem(this, newObjId, displayName, imgOffset, type, blockSize, blockCount, rootInum,
6124  firstInum, lastInum);
6125  } catch (SQLException ex) {
6126  throw new TskCoreException(String.format("Error creating file system with image offset %d and parent ID %d",
6127  imgOffset, parentObjId), ex);
6128  } finally {
6129  closeStatement(statement);
6131  }
6132  }
6133 
6159  public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
6160  String fileName,
6161  long metaAddr, int metaSeq,
6162  TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
6163  TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
6164  long ctime, long crtime, long atime, long mtime,
6165  boolean isFile, Content parent) throws TskCoreException {
6166 
6167  TimelineManager timelineManager = getTimelineManager();
6168 
6169  CaseDbTransaction transaction = beginTransaction();
6170  Statement queryStatement = null;
6171  try {
6172  CaseDbConnection connection = transaction.getConnection();
6173 
6174  // Insert a row for the local/logical file into the tsk_objects table.
6175  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6176  long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6177 
6178  String parentPath;
6179 
6180  if (parent instanceof AbstractFile) {
6181  AbstractFile parentFile = (AbstractFile) parent;
6182  if (isRootDirectory(parentFile, transaction)) {
6183  parentPath = "/";
6184  } else {
6185  parentPath = parentFile.getParentPath() + parent.getName() + "/"; //NON-NLS
6186  }
6187  } else {
6188  parentPath = "/";
6189  }
6190 
6191  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_SYSTEM_FILE);
6192  statement.clearParameters();
6193  statement.setLong(1, objectId); // obj_is
6194  statement.setLong(2, fsObjId); // fs_obj_id
6195  statement.setLong(3, dataSourceObjId); // data_source_obj_id
6196  statement.setShort(4, (short) attrType.getValue()); // attr_type
6197  statement.setInt(5, attrId); // attr_id
6198  statement.setString(6, fileName); // name
6199  statement.setLong(7, metaAddr); // meta_addr
6200  statement.setInt(8, metaSeq); // meta_addr
6201  statement.setShort(9, TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType()); //type
6202  statement.setShort(10, (short) 1); // has_path
6204  statement.setShort(11, dirType.getValue()); // dir_type
6206  statement.setShort(12, metaType.getValue()); // meta_type
6207  statement.setShort(13, dirFlag.getValue()); // dir_flags
6208  statement.setShort(14, metaFlags); // meta_flags
6209  statement.setLong(15, size < 0 ? 0 : size);
6210  statement.setLong(16, ctime);
6211  statement.setLong(17, crtime);
6212  statement.setLong(18, atime);
6213  statement.setLong(19, mtime);
6214  statement.setString(20, parentPath);
6215  final String extension = extractExtension(fileName);
6216  statement.setString(21, extension);
6217 
6218  connection.executeUpdate(statement);
6219 
6220  DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags,
6221  size, ctime, crtime, atime, mtime, null, null, parentPath, null, parent.getId(), null, null, extension);
6222 
6223  timelineManager.addEventsForNewFile(derivedFile, connection);
6224 
6225  transaction.commit();
6226  transaction = null;
6227 
6228  return new org.sleuthkit.datamodel.File(this, objectId, dataSourceObjId, fsObjId,
6229  attrType, attrId, fileName, metaAddr, metaSeq,
6230  dirType, metaType, dirFlag, metaFlags,
6231  size, ctime, crtime, atime, mtime,
6232  (short) 0, 0, 0, null, null, parentPath, null,
6233  extension);
6234 
6235  } catch (SQLException ex) {
6236  logger.log(Level.WARNING, "Failed to add file system file", ex);
6237  } finally {
6238  closeStatement(queryStatement);
6239  if (null != transaction) {
6240  try {
6241  transaction.rollback();
6242  } catch (TskCoreException ex2) {
6243  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6244  }
6245  }
6246  }
6247  return null;
6248  }
6249 
6258  public List<VirtualDirectory> getVirtualDirectoryRoots() throws TskCoreException {
6259  CaseDbConnection connection = connections.getConnection();
6261  Statement s = null;
6262  ResultSet rs = null;
6263  try {
6264  s = connection.createStatement();
6265  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE" //NON-NLS
6266  + " type = " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
6267  + " AND obj_id = data_source_obj_id"
6268  + " ORDER BY dir_type, LOWER(name)"); //NON-NLS
6269  List<VirtualDirectory> virtDirRootIds = new ArrayList<VirtualDirectory>();
6270  while (rs.next()) {
6271  virtDirRootIds.add(virtualDirectory(rs, connection));
6272  }
6273  return virtDirRootIds;
6274  } catch (SQLException ex) {
6275  throw new TskCoreException("Error getting local files virtual folder id", ex);
6276  } finally {
6277  closeResultSet(rs);
6278  closeStatement(s);
6279  connection.close();
6281  }
6282  }
6283 
6296  public final List<LayoutFile> addLayoutFiles(Content parent, List<TskFileRange> fileRanges) throws TskCoreException {
6297  assert (null != fileRanges);
6298  if (null == fileRanges) {
6299  throw new TskCoreException("TskFileRange object is null");
6300  }
6301 
6302  assert (null != parent);
6303  if (null == parent) {
6304  throw new TskCoreException("Conent is null");
6305  }
6306 
6307  CaseDbTransaction transaction = null;
6308  Statement statement = null;
6309  ResultSet resultSet = null;
6310 
6311  try {
6312  transaction = beginTransaction();
6313  CaseDbConnection connection = transaction.getConnection();
6314 
6315  List<LayoutFile> fileRangeLayoutFiles = new ArrayList<LayoutFile>();
6316  for (TskFileRange fileRange : fileRanges) {
6317  /*
6318  * Insert a row for the Tsk file range into the tsk_objects
6319  * table: INSERT INTO tsk_objects (par_obj_id, type) VALUES (?,
6320  * ?)
6321  */
6322  long fileRangeId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6323  long end_byte_in_parent = fileRange.getByteStart() + fileRange.getByteLen() - 1;
6324  /*
6325  * Insert a row for the Tsk file range into the tsk_files table:
6326  * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type,
6327  * has_path, dir_type, meta_type, dir_flags, meta_flags, size,
6328  * ctime, crtime, atime, mtime, md5, known, mime_type,
6329  * parent_path, data_source_obj_id,extension) VALUES (?, ?, ?,
6330  * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6331  */
6332  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6333  prepStmt.clearParameters();
6334  prepStmt.setLong(1, fileRangeId); // obj_id from tsk_objects
6335  prepStmt.setNull(2, java.sql.Types.BIGINT); // fs_obj_id
6336  prepStmt.setString(3, "Unalloc_" + parent.getId() + "_" + fileRange.getByteStart() + "_" + end_byte_in_parent); // name of form Unalloc_[image obj_id]_[start byte in parent]_[end byte in parent]
6337  prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()); // type
6338  prepStmt.setNull(5, java.sql.Types.BIGINT); // has_path
6339  prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
6340  prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
6341  prepStmt.setShort(8, TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()); // dir_flags
6342  prepStmt.setShort(9, TSK_FS_META_FLAG_ENUM.UNALLOC.getValue()); // nmeta_flags
6343  prepStmt.setLong(10, fileRange.getByteLen()); // size
6344  prepStmt.setNull(11, java.sql.Types.BIGINT); // ctime
6345  prepStmt.setNull(12, java.sql.Types.BIGINT); // crtime
6346  prepStmt.setNull(13, java.sql.Types.BIGINT); // atime
6347  prepStmt.setNull(14, java.sql.Types.BIGINT); // mtime
6348  prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
6349  prepStmt.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6350  prepStmt.setNull(17, java.sql.Types.VARCHAR); // MIME type
6351  prepStmt.setNull(18, java.sql.Types.VARCHAR); // parent path
6352  prepStmt.setLong(19, parent.getId()); // data_source_obj_id
6353 
6354  //extension, since this is not a FS file we just set it to null
6355  prepStmt.setString(20, null);
6356  connection.executeUpdate(prepStmt);
6357 
6358  /*
6359  * Insert a row in the tsk_layout_file table for each chunk of
6360  * the carved file. INSERT INTO tsk_file_layout (obj_id,
6361  * byte_start, byte_len, sequence) VALUES (?, ?, ?, ?)
6362  */
6363  prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
6364  prepStmt.clearParameters();
6365  prepStmt.setLong(1, fileRangeId); // obj_id
6366  prepStmt.setLong(2, fileRange.getByteStart()); // byte_start
6367  prepStmt.setLong(3, fileRange.getByteLen()); // byte_len
6368  prepStmt.setLong(4, fileRange.getSequence()); // sequence
6369  connection.executeUpdate(prepStmt);
6370 
6371  /*
6372  * Create a layout file representation of the carved file.
6373  */
6374  fileRangeLayoutFiles.add(new LayoutFile(this,
6375  fileRangeId,
6376  parent.getId(),
6377  Long.toString(fileRange.getSequence()),
6382  TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
6383  fileRange.getByteLen(),
6384  0L, 0L, 0L, 0L,
6385  null,
6387  parent.getUniquePath(),
6388  null));
6389  }
6390 
6391  transaction.commit();
6392  transaction = null;
6393  return fileRangeLayoutFiles;
6394 
6395  } catch (SQLException ex) {
6396  throw new TskCoreException("Failed to add layout files to case database", ex);
6397  } finally {
6398  closeResultSet(resultSet);
6399  closeStatement(statement);
6400 
6401  if (null != transaction) {
6402  try {
6403  transaction.rollback();
6404  } catch (TskCoreException ex2) {
6405  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6406  }
6407  }
6408  }
6409  }
6410 
6422  public final List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws TskCoreException {
6423  assert (null != carvingResult);
6424  if (null == carvingResult) {
6425  throw new TskCoreException("Carving is null");
6426  }
6427  assert (null != carvingResult.getParent());
6428  if (null == carvingResult.getParent()) {
6429  throw new TskCoreException("Carving result has null parent");
6430  }
6431  assert (null != carvingResult.getCarvedFiles());
6432  if (null == carvingResult.getCarvedFiles()) {
6433  throw new TskCoreException("Carving result has null carved files");
6434  }
6435  CaseDbTransaction transaction = null;
6436  Statement statement = null;
6437  ResultSet resultSet = null;
6438  long newCacheKey = 0; // Used to roll back cache if transaction is rolled back.
6439  try {
6440  transaction = beginTransaction();
6441  CaseDbConnection connection = transaction.getConnection();
6442 
6443  /*
6444  * Carved files are "re-parented" as children of the $CarvedFiles
6445  * virtual directory of the root file system, volume, or image
6446  * ancestor of the carved files parent, but if no such ancestor is
6447  * found, then the parent specified in the carving result is used.
6448  */
6449  Content root = carvingResult.getParent();
6450  while (null != root) {
6451  if (root instanceof FileSystem || root instanceof Volume || root instanceof Image) {
6452  break;
6453  }
6454  root = root.getParent();
6455  }
6456  if (null == root) {
6457  root = carvingResult.getParent();
6458  }
6459 
6460  /*
6461  * Get or create the $CarvedFiles virtual directory for the root
6462  * ancestor.
6463  */
6464  VirtualDirectory carvedFilesDir = rootIdsToCarvedFileDirs.get(root.getId());
6465  if (null == carvedFilesDir) {
6466  List<Content> rootChildren;
6467  if (root instanceof FileSystem) {
6468  rootChildren = ((FileSystem) root).getRootDirectory().getChildren();
6469  } else {
6470  rootChildren = root.getChildren();
6471  }
6472  for (Content child : rootChildren) {
6473  if (child instanceof VirtualDirectory && child.getName().equals(VirtualDirectory.NAME_CARVED)) {
6474  carvedFilesDir = (VirtualDirectory) child;
6475  break;
6476  }
6477  }
6478  if (null == carvedFilesDir) {
6479  long parId = root.getId();
6480  // $CarvedFiles should be a child of the root directory, not the file system
6481  if (root instanceof FileSystem) {
6482  Content rootDir = ((FileSystem) root).getRootDirectory();
6483  parId = rootDir.getId();
6484  }
6485  carvedFilesDir = addVirtualDirectory(parId, VirtualDirectory.NAME_CARVED, transaction);
6486  }
6487  newCacheKey = root.getId();
6488  rootIdsToCarvedFileDirs.put(newCacheKey, carvedFilesDir);
6489  }
6490 
6491  /*
6492  * Add the carved files to the database as children of the
6493  * $CarvedFile directory of the root ancestor.
6494  */
6495  String parentPath = getFileParentPath(carvedFilesDir.getId(), connection) + carvedFilesDir.getName() + "/";
6496  List<LayoutFile> carvedFiles = new ArrayList<LayoutFile>();
6497  for (CarvingResult.CarvedFile carvedFile : carvingResult.getCarvedFiles()) {
6498  /*
6499  * Insert a row for the carved file into the tsk_objects table:
6500  * INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6501  */
6502  long carvedFileId = addObject(carvedFilesDir.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6503 
6504  /*
6505  * Insert a row for the carved file into the tsk_files table:
6506  * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type,
6507  * has_path, dir_type, meta_type, dir_flags, meta_flags, size,
6508  * ctime, crtime, atime, mtime, md5, known, mime_type,
6509  * parent_path, data_source_obj_id,extenion) VALUES (?, ?, ?, ?,
6510  * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6511  */
6512  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6513  prepStmt.clearParameters();
6514  prepStmt.setLong(1, carvedFileId); // obj_id
6515  if (root instanceof FileSystem) {
6516  prepStmt.setLong(2, root.getId()); // fs_obj_id
6517  } else {
6518  prepStmt.setNull(2, java.sql.Types.BIGINT); // fs_obj_id
6519  }
6520  prepStmt.setString(3, carvedFile.getName()); // name
6521  prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()); // type
6522  prepStmt.setShort(5, (short) 1); // has_path
6523  prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
6524  prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
6525  prepStmt.setShort(8, TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()); // dir_flags
6526  prepStmt.setShort(9, TSK_FS_META_FLAG_ENUM.UNALLOC.getValue()); // nmeta_flags
6527  prepStmt.setLong(10, carvedFile.getSizeInBytes()); // size
6528  prepStmt.setNull(11, java.sql.Types.BIGINT); // ctime
6529  prepStmt.setNull(12, java.sql.Types.BIGINT); // crtime
6530  prepStmt.setNull(13, java.sql.Types.BIGINT); // atime
6531  prepStmt.setNull(14, java.sql.Types.BIGINT); // mtime
6532  prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
6533  prepStmt.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6534  prepStmt.setNull(17, java.sql.Types.VARCHAR); // MIME type
6535  prepStmt.setString(18, parentPath); // parent path
6536  prepStmt.setLong(19, carvedFilesDir.getDataSourceObjectId()); // data_source_obj_id
6537  prepStmt.setString(20, extractExtension(carvedFile.getName())); //extension
6538  connection.executeUpdate(prepStmt);
6539 
6540  /*
6541  * Insert a row in the tsk_layout_file table for each chunk of
6542  * the carved file. INSERT INTO tsk_file_layout (obj_id,
6543  * byte_start, byte_len, sequence) VALUES (?, ?, ?, ?)
6544  */
6545  prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
6546  for (TskFileRange tskFileRange : carvedFile.getLayoutInParent()) {
6547  prepStmt.clearParameters();
6548  prepStmt.setLong(1, carvedFileId); // obj_id
6549  prepStmt.setLong(2, tskFileRange.getByteStart()); // byte_start
6550  prepStmt.setLong(3, tskFileRange.getByteLen()); // byte_len
6551  prepStmt.setLong(4, tskFileRange.getSequence()); // sequence
6552  connection.executeUpdate(prepStmt);
6553  }
6554 
6555  /*
6556  * Create a layout file representation of the carved file.
6557  */
6558  carvedFiles.add(new LayoutFile(this,
6559  carvedFileId,
6560  carvedFilesDir.getDataSourceObjectId(),
6561  carvedFile.getName(),
6566  TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
6567  carvedFile.getSizeInBytes(),
6568  0L, 0L, 0L, 0L,
6569  null,
6571  parentPath,
6572  null));
6573  }
6574 
6575  transaction.commit();
6576  transaction = null;
6577  return carvedFiles;
6578 
6579  } catch (SQLException ex) {
6580  throw new TskCoreException("Failed to add carved files to case database", ex);
6581  } finally {
6582  closeResultSet(resultSet);
6583  closeStatement(statement);
6584 
6585  if (null != transaction) {
6586  try {
6587  transaction.rollback();
6588  } catch (TskCoreException ex2) {
6589  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6590  }
6591  if (0 != newCacheKey) {
6592  rootIdsToCarvedFileDirs.remove(newCacheKey);
6593  }
6594  }
6595  }
6596  }
6597 
6628  public DerivedFile addDerivedFile(String fileName, String localPath,
6629  long size, long ctime, long crtime, long atime, long mtime,
6630  boolean isFile, Content parentObj,
6631  String rederiveDetails, String toolName, String toolVersion,
6632  String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
6633  // Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
6634  localPath = localPath.replaceAll("^[/\\\\]+", "");
6635 
6636  TimelineManager timelineManager = getTimelineManager();
6637 
6638  CaseDbTransaction transaction = beginTransaction();
6639  CaseDbConnection connection = transaction.getConnection();
6640  try {
6641  final long parentId = parentObj.getId();
6642  String parentPath = "";
6643  if (parentObj instanceof BlackboardArtifact) {
6644  parentPath = parentObj.getUniquePath() + '/' + parentObj.getName() + '/';
6645  } else if (parentObj instanceof AbstractFile) {
6646  parentPath = ((AbstractFile) parentObj).getParentPath() + parentObj.getName() + '/'; //NON-NLS
6647  }
6648 
6649  // Insert a row for the derived file into the tsk_objects table.
6650  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6651  long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6652 
6653  // Insert a row for the virtual directory into the tsk_files table.
6654  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
6655  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type,
6656  // parent_path, data_source_obj_id, extension)
6657  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6658  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6659  statement.clearParameters();
6660  statement.setLong(1, newObjId);
6661 
6662  // If the parentFile is part of a file system, use its file system object ID.
6663  long fsObjId = this.getFileSystemId(parentId, connection);
6664  if (fsObjId != -1) {
6665  statement.setLong(2, fsObjId);
6666  } else {
6667  statement.setNull(2, java.sql.Types.BIGINT);
6668  }
6669  statement.setString(3, fileName);
6670 
6671  //type, has_path
6672  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType());
6673  statement.setShort(5, (short) 1);
6674 
6675  //flags
6677  statement.setShort(6, dirType.getValue());
6679  statement.setShort(7, metaType.getValue());
6680 
6681  //note: using alloc under assumption that derived files derive from alloc files
6683  statement.setShort(8, dirFlag.getValue());
6684  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
6685  | TSK_FS_META_FLAG_ENUM.USED.getValue());
6686  statement.setShort(9, metaFlags);
6687 
6688  //size
6689  //prevent negative size
6690  long savedSize = size < 0 ? 0 : size;
6691  statement.setLong(10, savedSize);
6692 
6693  //mactimes
6694  //long ctime, long crtime, long atime, long mtime,
6695  statement.setLong(11, ctime);
6696  statement.setLong(12, crtime);
6697  statement.setLong(13, atime);
6698  statement.setLong(14, mtime);
6699 
6700  statement.setNull(15, java.sql.Types.VARCHAR); // MD5
6701  statement.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6702  statement.setNull(17, java.sql.Types.VARCHAR); // MIME type
6703 
6704  //parent path
6705  statement.setString(18, parentPath);
6706 
6707  // root data source object id
6708  long dataSourceObjId = getDataSourceObjectId(connection, parentId);
6709  statement.setLong(19, dataSourceObjId);
6710  final String extension = extractExtension(fileName);
6711  //extension
6712  statement.setString(20, extension);
6713 
6714  connection.executeUpdate(statement);
6715 
6716  //add localPath
6717  addFilePath(connection, newObjId, localPath, encodingType);
6718 
6719  DerivedFile derivedFile = new DerivedFile(this, newObjId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags,
6720  savedSize, ctime, crtime, atime, mtime, null, null, parentPath, localPath, parentId, null, encodingType, extension);
6721 
6722  timelineManager.addEventsForNewFile(derivedFile, connection);
6723  transaction.commit();
6724  //TODO add derived method to tsk_files_derived and tsk_files_derived_method
6725  return derivedFile;
6726  } catch (SQLException ex) {
6727  connection.rollbackTransaction();
6728  throw new TskCoreException("Failed to add derived file to case database", ex);
6729  } finally {
6730  connection.close();
6731  }
6732  }
6733 
6764  public DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath,
6765  long size, long ctime, long crtime, long atime, long mtime,
6766  boolean isFile, String mimeType,
6767  String rederiveDetails, String toolName, String toolVersion,
6768  String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
6769 
6770  // Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
6771  localPath = localPath.replaceAll("^[/\\\\]+", "");
6772 
6773  CaseDbConnection connection = connections.getConnection();
6775  ResultSet rs = null;
6776  try {
6777  Content parentObj = derivedFile.getParent();
6778  connection.beginTransaction();
6779  final long parentId = parentObj.getId();
6780  String parentPath = "";
6781  if (parentObj instanceof BlackboardArtifact) {
6782  parentPath = parentObj.getUniquePath() + '/' + parentObj.getName() + '/';
6783  } else if (parentObj instanceof AbstractFile) {
6784  parentPath = ((AbstractFile) parentObj).getParentPath() + parentObj.getName() + '/'; //NON-NLS
6785  }
6786  // UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, "
6787  // + "size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? WHERE obj_id = ?"), //NON-NLS
6788  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_DERIVED_FILE);
6789  statement.clearParameters();
6790 
6791  //type
6792  statement.setShort(1, TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType());
6793 
6794  //flags
6796  statement.setShort(2, dirType.getValue());
6798  statement.setShort(3, metaType.getValue());
6799 
6800  //note: using alloc under assumption that derived files derive from alloc files
6802  statement.setShort(4, dirFlag.getValue());
6803  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
6804  | TSK_FS_META_FLAG_ENUM.USED.getValue());
6805  statement.setShort(5, metaFlags);
6806 
6807  //size
6808  //prevent negative size
6809  long savedSize = size < 0 ? 0 : size;
6810  statement.setLong(6, savedSize);
6811 
6812  //mactimes
6813  //long ctime, long crtime, long atime, long mtime,
6814  statement.setLong(7, ctime);
6815  statement.setLong(8, crtime);
6816  statement.setLong(9, atime);
6817  statement.setLong(10, mtime);
6818  statement.setString(11, mimeType);
6819  statement.setString(12, String.valueOf(derivedFile.getId()));
6820  connection.executeUpdate(statement);
6821 
6822  //add localPath
6823  updateFilePath(connection, derivedFile.getId(), localPath, encodingType);
6824 
6825  connection.commitTransaction();
6826 
6827  long dataSourceObjId = getDataSourceObjectId(connection, parentId);
6828  final String extension = extractExtension(derivedFile.getName());
6829  return new DerivedFile(this, derivedFile.getId(), dataSourceObjId, derivedFile.getName(), dirType, metaType, dirFlag, metaFlags,
6830  savedSize, ctime, crtime, atime, mtime, null, null, parentPath, localPath, parentId, null, encodingType, extension);
6831  } catch (SQLException ex) {
6832  connection.rollbackTransaction();
6833  throw new TskCoreException("Failed to add derived file to case database", ex);
6834  } finally {
6835  closeResultSet(rs);
6836  connection.close();
6838  }
6839  }
6840 
6860  public LocalFile addLocalFile(String fileName, String localPath,
6861  long size, long ctime, long crtime, long atime, long mtime,
6862  boolean isFile, TskData.EncodingType encodingType,
6863  AbstractFile parent) throws TskCoreException {
6864 
6865  CaseDbTransaction localTrans = beginTransaction();
6866  try {
6867  LocalFile created = addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile, encodingType, parent, localTrans);
6868  localTrans.commit();
6869  localTrans = null;
6870  return created;
6871  } finally {
6872  if (null != localTrans) {
6873  try {
6874  localTrans.rollback();
6875  } catch (TskCoreException ex2) {
6876  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6877  }
6878  }
6879  }
6880  }
6881 
6906  public LocalFile addLocalFile(String fileName, String localPath,
6907  long size, long ctime, long crtime, long atime, long mtime,
6908  boolean isFile, TskData.EncodingType encodingType,
6909  Content parent, CaseDbTransaction transaction) throws TskCoreException {
6910 
6911  return addLocalFile(fileName, localPath,
6912  size, ctime, crtime, atime, mtime,
6913  null, null, null,
6914  isFile, encodingType,
6915  parent, transaction);
6916  }
6917 
6945  public LocalFile addLocalFile(String fileName, String localPath,
6946  long size, long ctime, long crtime, long atime, long mtime,
6947  String md5, FileKnown known, String mimeType,
6948  boolean isFile, TskData.EncodingType encodingType,
6949  Content parent, CaseDbTransaction transaction) throws TskCoreException {
6950  CaseDbConnection connection = transaction.getConnection();
6951  Statement queryStatement = null;
6952  try {
6953 
6954  // Insert a row for the local/logical file into the tsk_objects table.
6955  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6956  long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6957 
6958  // Insert a row for the local/logical file into the tsk_files table.
6959  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
6960  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type,
6961  // parent_path, data_source_obj_id,extension)
6962  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6963  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6964  statement.clearParameters();
6965  statement.setLong(1, objectId);
6966  statement.setNull(2, java.sql.Types.BIGINT); // Not part of a file system
6967  statement.setString(3, fileName);
6968  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType());
6969  statement.setShort(5, (short) 1);
6971  statement.setShort(6, dirType.getValue());
6973  statement.setShort(7, metaType.getValue());
6975  statement.setShort(8, dirFlag.getValue());
6976  short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue() | TSK_FS_META_FLAG_ENUM.USED.getValue());
6977  statement.setShort(9, metaFlags);
6978  //prevent negative size
6979  long savedSize = size < 0 ? 0 : size;
6980  statement.setLong(10, savedSize);
6981  statement.setLong(11, ctime);
6982  statement.setLong(12, crtime);
6983  statement.setLong(13, atime);
6984  statement.setLong(14, mtime);
6985  statement.setString(15, md5);
6986  if (known != null) {
6987  statement.setByte(16, known.getFileKnownValue());
6988  } else {
6989  statement.setByte(16, FileKnown.UNKNOWN.getFileKnownValue());
6990  }
6991  statement.setString(17, mimeType);
6992  String parentPath;
6993  long dataSourceObjId;
6994 
6995  if (parent instanceof AbstractFile) {
6996  AbstractFile parentFile = (AbstractFile) parent;
6997  if (isRootDirectory(parentFile, transaction)) {
6998  parentPath = "/";
6999  } else {
7000  parentPath = parentFile.getParentPath() + parent.getName() + "/"; //NON-NLS
7001  }
7002  dataSourceObjId = parentFile.getDataSourceObjectId();
7003  } else {
7004  parentPath = "/";
7005  dataSourceObjId = getDataSourceObjectId(connection, parent.getId());
7006  }
7007  statement.setString(18, parentPath);
7008  statement.setLong(19, dataSourceObjId);
7009  final String extension = extractExtension(fileName);
7010  statement.setString(20, extension);
7011 
7012  connection.executeUpdate(statement);
7013  addFilePath(connection, objectId, localPath, encodingType);
7014  LocalFile localFile = new LocalFile(this,
7015  objectId,
7016  fileName,
7018  dirType,
7019  metaType,
7020  dirFlag,
7021  metaFlags,
7022  savedSize,
7023  ctime, crtime, atime, mtime,
7024  mimeType, md5, known,
7025  parent.getId(), parentPath,
7026  dataSourceObjId,
7027  localPath,
7028  encodingType, extension);
7029  getTimelineManager().addEventsForNewFile(localFile, connection);
7030  return localFile;
7031 
7032  } catch (SQLException ex) {
7033  throw new TskCoreException(String.format("Failed to INSERT local file %s (%s) with parent id %d in tsk_files table", fileName, localPath, parent.getId()), ex);
7034  } finally {
7035  closeStatement(queryStatement);
7036  }
7037  }
7038 
7051  private boolean isRootDirectory(AbstractFile file, CaseDbTransaction transaction) throws TskCoreException {
7052  CaseDbConnection connection = transaction.getConnection();
7053  Statement statement = null;
7054  ResultSet resultSet = null;
7055 
7056  try {
7057  String query = String.format("SELECT ParentRow.type AS parent_type, ParentRow.obj_id AS parent_object_id "
7058  + "FROM tsk_objects ParentRow JOIN tsk_objects ChildRow ON ChildRow.par_obj_id = ParentRow.obj_id "
7059  + "WHERE ChildRow.obj_id = %s;", file.getId());
7060 
7061  statement = connection.createStatement();
7062  resultSet = statement.executeQuery(query);
7063  if (resultSet.next()) {
7064  long parentId = resultSet.getLong("parent_object_id");
7065  if (parentId == 0) {
7066  return true;
7067  }
7068  int type = resultSet.getInt("parent_type");
7069  return (type == TskData.ObjectType.IMG.getObjectType()
7070  || type == TskData.ObjectType.VS.getObjectType()
7071  || type == TskData.ObjectType.VOL.getObjectType()
7072  || type == TskData.ObjectType.FS.getObjectType());
7073 
7074  } else {
7075  return true; // The file has no parent
7076  }
7077  } catch (SQLException ex) {
7078  throw new TskCoreException(String.format("Failed to lookup parent of file (%s) with id %d", file.getName(), file.getId()), ex);
7079  } finally {
7080  closeResultSet(resultSet);
7081  closeStatement(statement);
7082  }
7083  }
7084 
7104  public LayoutFile addLayoutFile(String fileName,
7105  long size,
7106  TSK_FS_NAME_FLAG_ENUM dirFlag, TSK_FS_META_FLAG_ENUM metaFlag,
7107  long ctime, long crtime, long atime, long mtime,
7108  List<TskFileRange> fileRanges,
7109  Content parent) throws TskCoreException {
7110 
7111  if (null == parent) {
7112  throw new TskCoreException("Parent can not be null");
7113  }
7114 
7115  String parentPath;
7116  if (parent instanceof AbstractFile) {
7117  parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + '/'; //NON-NLS
7118  } else {
7119  parentPath = "/";
7120  }
7121 
7122  CaseDbTransaction transaction = null;
7123  Statement statement = null;
7124  ResultSet resultSet = null;
7125  try {
7126  transaction = beginTransaction();
7127  CaseDbConnection connection = transaction.getConnection();
7128 
7129  /*
7130  * Insert a row for the layout file into the tsk_objects table:
7131  * INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
7132  */
7133  long newFileId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
7134 
7135  /*
7136  * Insert a row for the file into the tsk_files table: INSERT INTO
7137  * tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type,
7138  * meta_type, dir_flags, meta_flags, size, ctime, crtime, atime,
7139  * mtime, md5, known, mime_type, parent_path,
7140  * data_source_obj_id,extenion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,
7141  * ?, ?, ?, ?, ?, ?, ?,?)
7142  */
7143  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
7144  prepStmt.clearParameters();
7145  prepStmt.setLong(1, newFileId); // obj_id
7146 
7147  // If the parent is part of a file system, grab its file system ID
7148  if (0 != parent.getId()) {
7149  long parentFs = this.getFileSystemId(parent.getId(), connection);
7150  if (parentFs != -1) {
7151  prepStmt.setLong(2, parentFs);
7152  } else {
7153  prepStmt.setNull(2, java.sql.Types.BIGINT);
7154  }
7155  } else {
7156  prepStmt.setNull(2, java.sql.Types.BIGINT);
7157  }
7158  prepStmt.setString(3, fileName); // name
7159  prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType()); // type
7160  prepStmt.setShort(5, (short) 0); // has_path
7161  prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
7162  prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
7163  prepStmt.setShort(8, dirFlag.getValue()); // dir_flags
7164  prepStmt.setShort(9, metaFlag.getValue()); // meta_flags
7165  //prevent negative size
7166  long savedSize = size < 0 ? 0 : size;
7167  prepStmt.setLong(10, savedSize); // size
7168  prepStmt.setLong(11, ctime); // ctime
7169  prepStmt.setLong(12, crtime); // crtime
7170  prepStmt.setLong(13, atime); // atime
7171  prepStmt.setLong(14, mtime); // mtime
7172  prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
7173  prepStmt.setByte(16, FileKnown.UNKNOWN.getFileKnownValue()); // Known
7174  prepStmt.setNull(17, java.sql.Types.VARCHAR); // MIME type
7175  prepStmt.setString(18, parentPath); // parent path
7176  prepStmt.setLong(19, parent.getDataSource().getId()); // data_source_obj_id
7177 
7178  prepStmt.setString(20, extractExtension(fileName)); //extension
7179  connection.executeUpdate(prepStmt);
7180 
7181  /*
7182  * Insert a row in the tsk_layout_file table for each chunk of the
7183  * carved file. INSERT INTO tsk_file_layout (obj_id, byte_start,
7184  * byte_len, sequence) VALUES (?, ?, ?, ?)
7185  */
7186  prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
7187  for (TskFileRange tskFileRange : fileRanges) {
7188  prepStmt.clearParameters();
7189  prepStmt.setLong(1, newFileId); // obj_id
7190  prepStmt.setLong(2, tskFileRange.getByteStart()); // byte_start
7191  prepStmt.setLong(3, tskFileRange.getByteLen()); // byte_len
7192  prepStmt.setLong(4, tskFileRange.getSequence()); // sequence
7193  connection.executeUpdate(prepStmt);
7194  }
7195 
7196  /*
7197  * Create a layout file representation of the carved file.
7198  */
7199  LayoutFile layoutFile = new LayoutFile(this,
7200  newFileId,
7201  parent.getDataSource().getId(),
7202  fileName,
7206  dirFlag,
7207  metaFlag.getValue(),
7208  savedSize,
7209  ctime, crtime, atime, mtime,
7210  null,
7212  parentPath,
7213  null);
7214 
7215  transaction.commit();
7216  transaction = null;
7217  return layoutFile;
7218 
7219  } catch (SQLException ex) {
7220  throw new TskCoreException("Failed to add layout file " + fileName + " to case database", ex);
7221  } finally {
7222  closeResultSet(resultSet);
7223  closeStatement(statement);
7224 
7225  if (null != transaction) {
7226  try {
7227  transaction.rollback();
7228  } catch (TskCoreException ex2) {
7229  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
7230  }
7231  }
7232  }
7233  }
7234 
7247  private long getDataSourceObjectId(CaseDbConnection connection, long objectId) throws TskCoreException {
7249  Statement statement = null;
7250  ResultSet resultSet = null;
7251  try {
7252  statement = connection.createStatement();
7253  long dataSourceObjId;
7254  long ancestorId = objectId;
7255  do {
7256  dataSourceObjId = ancestorId;
7257  String query = String.format("SELECT par_obj_id FROM tsk_objects WHERE obj_id = %s;", ancestorId);
7258  resultSet = statement.executeQuery(query);
7259  if (resultSet.next()) {
7260  ancestorId = resultSet.getLong("par_obj_id");
7261  } else {
7262  throw new TskCoreException(String.format("tsk_objects table is corrupt, SQL query returned no result: %s", query));
7263  }
7264  resultSet.close();
7265  resultSet = null;
7266  } while (0 != ancestorId); // Not NULL
7267  return dataSourceObjId;
7268  } catch (SQLException ex) {
7269  throw new TskCoreException(String.format("Error finding root data source for object (obj_id = %d)", objectId), ex);
7270  } finally {
7271  closeResultSet(resultSet);
7272  closeStatement(statement);
7274  }
7275  }
7276 
7288  private void addFilePath(CaseDbConnection connection, long objId, String path, TskData.EncodingType type) throws SQLException {
7289  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LOCAL_PATH);
7290  statement.clearParameters();
7291  statement.setLong(1, objId);
7292  statement.setString(2, path);
7293  statement.setInt(3, type.getType());
7294  connection.executeUpdate(statement);
7295  }
7296 
7308  private void updateFilePath(CaseDbConnection connection, long objId, String path, TskData.EncodingType type) throws SQLException {
7309  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_LOCAL_PATH);
7310  statement.clearParameters();
7311  statement.setString(1, path);
7312  statement.setInt(2, type.getType());
7313  statement.setLong(3, objId);
7314  connection.executeUpdate(statement);
7315  }
7316 
7332  public List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException {
7333  return findFiles(dataSource, fileName, parentFile.getName());
7334  }
7335 
7347  public long countFilesWhere(String sqlWhereClause) throws TskCoreException {
7348  CaseDbConnection connection = connections.getConnection();
7350  Statement s = null;
7351  ResultSet rs = null;
7352  try {
7353  s = connection.createStatement();
7354  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
7355  rs.next();
7356  return rs.getLong("count");
7357  } catch (SQLException e) {
7358  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.countFilesWhere().", e);
7359  } finally {
7360  closeResultSet(rs);
7361  closeStatement(s);
7362  connection.close();
7364  }
7365  }
7366 
7384  public List<AbstractFile> findAllFilesWhere(String sqlWhereClause) throws TskCoreException {
7385  CaseDbConnection connection = connections.getConnection();
7387  Statement s = null;
7388  ResultSet rs = null;
7389  try {
7390  s = connection.createStatement();
7391  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
7392  return resultSetToAbstractFiles(rs, connection);
7393  } catch (SQLException e) {
7394  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFilesWhere(): " + sqlWhereClause, e);
7395  } finally {
7396  closeResultSet(rs);
7397  closeStatement(s);
7398  connection.close();
7400  }
7401  }
7402 
7415  public List<Long> findAllFileIdsWhere(String sqlWhereClause) throws TskCoreException {
7416  CaseDbConnection connection = connections.getConnection();
7418  Statement s = null;
7419  ResultSet rs = null;
7420  try {
7421  s = connection.createStatement();
7422  rs = connection.executeQuery(s, "SELECT obj_id FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
7423  List<Long> ret = new ArrayList<Long>();
7424  while (rs.next()) {
7425  ret.add(rs.getLong("obj_id"));
7426  }
7427  return ret;
7428  } catch (SQLException e) {
7429  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFileIdsWhere(): " + sqlWhereClause, e);
7430  } finally {
7431  closeResultSet(rs);
7432  closeStatement(s);
7433  connection.close();
7435  }
7436  }
7437 
7449  public List<AbstractFile> openFiles(Content dataSource, String filePath) throws TskCoreException {
7450 
7451  // get the non-unique path (strip of image and volume path segments, if
7452  // the exist.
7453  String path = AbstractFile.createNonUniquePath(filePath).toLowerCase();
7454 
7455  // split the file name from the parent path
7456  int lastSlash = path.lastIndexOf('/'); //NON-NLS
7457 
7458  // if the last slash is at the end, strip it off
7459  if (lastSlash == path.length()) {
7460  path = path.substring(0, lastSlash - 1);
7461  lastSlash = path.lastIndexOf('/'); //NON-NLS
7462  }
7463 
7464  String parentPath = path.substring(0, lastSlash);
7465  String fileName = path.substring(lastSlash);
7466 
7467  return findFiles(dataSource, fileName, parentPath);
7468  }
7469 
7480  public List<TskFileRange> getFileRanges(long id) throws TskCoreException {
7481  CaseDbConnection connection = connections.getConnection();
7483  Statement s = null;
7484  ResultSet rs = null;
7485  try {
7486  s = connection.createStatement();
7487  rs = connection.executeQuery(s, "SELECT * FROM tsk_file_layout WHERE obj_id = " + id + " ORDER BY sequence");
7488  List<TskFileRange> ranges = new ArrayList<TskFileRange>();
7489  while (rs.next()) {
7490  TskFileRange range = new TskFileRange(rs.getLong("byte_start"), //NON-NLS
7491  rs.getLong("byte_len"), rs.getLong("sequence")); //NON-NLS
7492  ranges.add(range);
7493  }
7494  return ranges;
7495  } catch (SQLException ex) {
7496  throw new TskCoreException("Error getting TskFileLayoutRanges by id, id = " + id, ex);
7497  } finally {
7498  closeResultSet(rs);
7499  closeStatement(s);
7500  connection.close();
7502  }
7503  }
7504 
7515  public Image getImageById(long id) throws TskCoreException {
7516  CaseDbConnection connection = connections.getConnection();
7518  Statement s1 = null;
7519  ResultSet rs1 = null;
7520  Statement s2 = null;
7521  ResultSet rs2 = null;
7522  try {
7523  s1 = connection.createStatement();
7524  rs1 = connection.executeQuery(s1, "SELECT tsk_image_info.type, tsk_image_info.ssize, tsk_image_info.tzone, tsk_image_info.size, tsk_image_info.md5, tsk_image_info.sha1, tsk_image_info.sha256, tsk_image_info.display_name, data_source_info.device_id "
7525  + "FROM tsk_image_info "
7526  + "INNER JOIN data_source_info ON tsk_image_info.obj_id = data_source_info.obj_id "
7527  + "WHERE tsk_image_info.obj_id = " + id); //NON-NLS
7528  if (rs1.next()) {
7529  s2 = connection.createStatement();
7530  rs2 = connection.executeQuery(s2, "SELECT name FROM tsk_image_names WHERE tsk_image_names.obj_id = " + id); //NON-NLS
7531  List<String> imagePaths = new ArrayList<String>();
7532  while (rs2.next()) {
7533  imagePaths.add(rs2.getString("name"));
7534  }
7535  long type = rs1.getLong("type"); //NON-NLS
7536  long ssize = rs1.getLong("ssize"); //NON-NLS
7537  String tzone = rs1.getString("tzone"); //NON-NLS
7538  long size = rs1.getLong("size"); //NON-NLS
7539  String md5 = rs1.getString("md5"); //NON-NLS
7540  String sha1 = rs1.getString("sha1"); //NON-NLS
7541  String sha256 = rs1.getString("sha256"); //NON-NLS
7542  String name = rs1.getString("display_name");
7543  if (name == null) {
7544  if (imagePaths.size() > 0) {
7545  String path = imagePaths.get(0);
7546  name = (new java.io.File(path)).getName();
7547  } else {
7548  name = "";
7549  }
7550  }
7551  String device_id = rs1.getString("device_id");
7552 
7553  return new Image(this, id, type, device_id, ssize, name,
7554  imagePaths.toArray(new String[imagePaths.size()]), tzone, md5, sha1, sha256, size);
7555  } else {
7556  throw new TskCoreException("No image found for id: " + id);
7557  }
7558  } catch (SQLException ex) {
7559  throw new TskCoreException("Error getting Image by id, id = " + id, ex);
7560  } finally {
7561  closeResultSet(rs2);
7562  closeStatement(s2);
7563  closeResultSet(rs1);
7564  closeStatement(s1);
7565  connection.close();
7567  }
7568  }
7569 
7581  VolumeSystem getVolumeSystemById(long id, Content parent) throws TskCoreException {
7582  CaseDbConnection connection = connections.getConnection();
7584  Statement s = null;
7585  ResultSet rs = null;
7586  try {
7587  s = connection.createStatement();
7588  rs = connection.executeQuery(s, "SELECT * FROM tsk_vs_info " //NON-NLS
7589  + "where obj_id = " + id); //NON-NLS
7590  if (rs.next()) {
7591  long type = rs.getLong("vs_type"); //NON-NLS
7592  long imgOffset = rs.getLong("img_offset"); //NON-NLS
7593  long blockSize = rs.getLong("block_size"); //NON-NLS
7594  VolumeSystem vs = new VolumeSystem(this, id, "", type, imgOffset, blockSize);
7595  vs.setParent(parent);
7596  return vs;
7597  } else {
7598  throw new TskCoreException("No volume system found for id:" + id);
7599  }
7600  } catch (SQLException ex) {
7601  throw new TskCoreException("Error getting Volume System by ID.", ex);
7602  } finally {
7603  closeResultSet(rs);
7604  closeStatement(s);
7605  connection.close();
7607  }
7608  }
7609 
7618  VolumeSystem getVolumeSystemById(long id, long parentId) throws TskCoreException {
7619  VolumeSystem vs = getVolumeSystemById(id, null);
7620  vs.setParentId(parentId);
7621  return vs;
7622  }
7623 
7635  FileSystem getFileSystemById(long id, Image parent) throws TskCoreException {
7636  return getFileSystemByIdHelper(id, parent);
7637  }
7638 
7647  FileSystem getFileSystemById(long id, long parentId) throws TskCoreException {
7648  Volume vol = null;
7649  FileSystem fs = getFileSystemById(id, vol);
7650  fs.setParentId(parentId);
7651  return fs;
7652  }
7653 
7665  FileSystem getFileSystemById(long id, Volume parent) throws TskCoreException {
7666  return getFileSystemByIdHelper(id, parent);
7667  }
7668 
7680  Pool getPoolById(long id, Content parent) throws TskCoreException {
7681  return getPoolByIdHelper(id, parent);
7682  }
7683 
7692  Pool getPoolById(long id, long parentId) throws TskCoreException {
7693  Pool pool = getPoolById(id, null);
7694  pool.setParentId(parentId);
7695  return pool;
7696  }
7697 
7709  private Pool getPoolByIdHelper(long id, Content parent) throws TskCoreException {
7710 
7712  try (CaseDbConnection connection = connections.getConnection();
7713  Statement s = connection.createStatement();
7714  ResultSet rs = connection.executeQuery(s, "SELECT * FROM tsk_pool_info " //NON-NLS
7715  + "where obj_id = " + id);) { //NON-NLS
7716  if (rs.next()) {
7717  Pool pool = new Pool(this, rs.getLong("obj_id"), TskData.TSK_POOL_TYPE_ENUM.valueOf(rs.getLong("pool_type")).getName(), rs.getLong("pool_type"));
7718  pool.setParent(parent);
7719 
7720  return pool;
7721  } else {
7722  throw new TskCoreException("No pool found for ID:" + id);
7723  }
7724  } catch (SQLException ex) {
7725  throw new TskCoreException("Error getting Pool by ID", ex);
7726  } finally {
7728  }
7729  }
7730 
7742  private FileSystem getFileSystemByIdHelper(long id, Content parent) throws TskCoreException {
7743  // see if we already have it
7744  // @@@ NOTE: this is currently kind of bad in that we are ignoring the parent value,
7745  // but it should be the same...
7746  synchronized (fileSystemIdMap) {
7747  if (fileSystemIdMap.containsKey(id)) {
7748  return fileSystemIdMap.get(id);
7749  }
7750  }
7751  CaseDbConnection connection = connections.getConnection();
7753  Statement s = null;
7754  ResultSet rs = null;
7755  try {
7756  s = connection.createStatement();
7757  rs = connection.executeQuery(s, "SELECT * FROM tsk_fs_info " //NON-NLS
7758  + "where obj_id = " + id); //NON-NLS
7759  if (rs.next()) {
7760  TskData.TSK_FS_TYPE_ENUM fsType = TskData.TSK_FS_TYPE_ENUM.valueOf(rs.getInt("fs_type")); //NON-NLS
7761  FileSystem fs = new FileSystem(this, rs.getLong("obj_id"), "", rs.getLong("img_offset"), //NON-NLS
7762  fsType, rs.getLong("block_size"), rs.getLong("block_count"), //NON-NLS
7763  rs.getLong("root_inum"), rs.getLong("first_inum"), rs.getLong("last_inum")); //NON-NLS
7764  fs.setParent(parent);
7765  // save it for the next call
7766  synchronized (fileSystemIdMap) {
7767  fileSystemIdMap.put(id, fs);
7768  }
7769  return fs;
7770  } else {
7771  throw new TskCoreException("No file system found for id:" + id);
7772  }
7773  } catch (SQLException ex) {
7774  throw new TskCoreException("Error getting File System by ID", ex);
7775  } finally {
7776  closeResultSet(rs);
7777  closeStatement(s);
7778  connection.close();
7780  }
7781  }
7782 
7794  Volume getVolumeById(long id, VolumeSystem parent) throws TskCoreException {
7795  CaseDbConnection connection = connections.getConnection();
7797  Statement s = null;
7798  ResultSet rs = null;
7799  try {
7800  s = connection.createStatement();
7801  rs = connection.executeQuery(s, "SELECT * FROM tsk_vs_parts " //NON-NLS
7802  + "where obj_id = " + id); //NON-NLS
7803  if (rs.next()) {
7811  String description;
7812  try {
7813  description = rs.getString("desc");
7814  } catch (Exception ex) {
7815  description = rs.getString("descr");
7816  }
7817  Volume vol = new Volume(this, rs.getLong("obj_id"), rs.getLong("addr"), //NON-NLS
7818  rs.getLong("start"), rs.getLong("length"), rs.getLong("flags"), //NON-NLS
7819  description);
7820  vol.setParent(parent);
7821  return vol;
7822  } else {
7823  throw new TskCoreException("No volume found for id:" + id);
7824  }
7825  } catch (SQLException ex) {
7826  throw new TskCoreException("Error getting Volume by ID", ex);
7827  } finally {
7828  closeResultSet(rs);
7829  closeStatement(s);
7830  connection.close();
7832  }
7833  }
7834 
7843  Volume getVolumeById(long id, long parentId) throws TskCoreException {
7844  Volume vol = getVolumeById(id, null);
7845  vol.setParentId(parentId);
7846  return vol;
7847  }
7848 
7860  Directory getDirectoryById(long id, FileSystem parentFs) throws TskCoreException {
7861  CaseDbConnection connection = connections.getConnection();
7863  Statement s = null;
7864  ResultSet rs = null;
7865  try {
7866  s = connection.createStatement();
7867  rs = connection.executeQuery(s, "SELECT * FROM tsk_files " //NON-NLS
7868  + "WHERE obj_id = " + id);
7869  Directory temp = null; //NON-NLS
7870  if (rs.next()) {
7871  final short type = rs.getShort("type"); //NON-NLS
7872  if (type == TSK_DB_FILES_TYPE_ENUM.FS.getFileType()) {
7873  if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
7874  || rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()) { //NON-NLS
7875  temp = directory(rs, parentFs);
7876  }
7877  } else if (type == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()) {
7878  throw new TskCoreException("Expecting an FS-type directory, got virtual, id: " + id);
7879  }
7880  } else {
7881  throw new TskCoreException("No Directory found for id:" + id);
7882  }
7883  return temp;
7884  } catch (SQLException ex) {
7885  throw new TskCoreException("Error getting Directory by ID", ex);
7886  } finally {
7887  closeResultSet(rs);
7888  closeStatement(s);
7889  connection.close();
7891  }
7892  }
7893 
7903  public Collection<FileSystem> getImageFileSystems(Image image) throws TskCoreException {
7904  List<FileSystem> fileSystems = new ArrayList<>();
7905  CaseDbConnection connection = connections.getConnection();
7906 
7908  Statement s = null;
7909  ResultSet rs = null;
7910  String queryStr = "SELECT * FROM tsk_fs_info WHERE data_source_obj_id = " + image.getId();
7911  try {
7912  s = connection.createStatement();
7913  rs = connection.executeQuery(s, queryStr); //NON-NLS
7914  while (rs.next()) {
7915  TskData.TSK_FS_TYPE_ENUM fsType = TskData.TSK_FS_TYPE_ENUM.valueOf(rs.getInt("fs_type")); //NON-NLS
7916  FileSystem fs = new FileSystem(this, rs.getLong("obj_id"), "", rs.getLong("img_offset"), //NON-NLS
7917  fsType, rs.getLong("block_size"), rs.getLong("block_count"), //NON-NLS
7918  rs.getLong("root_inum"), rs.getLong("first_inum"), rs.getLong("last_inum")); //NON-NLS
7919  fs.setParent(null);
7920  fileSystems.add(fs);
7921  }
7922  } catch (SQLException ex) {
7923  throw new TskCoreException("Error looking up files systems. Query: " + queryStr, ex); //NON-NLS
7924  } finally {
7925  closeResultSet(rs);
7926  closeStatement(s);
7927  connection.close();
7929  }
7930  return fileSystems;
7931  }
7932 
7943  List<Content> getImageChildren(Image img) throws TskCoreException {
7944  Collection<ObjectInfo> childInfos = getChildrenInfo(img);
7945  List<Content> children = new ArrayList<Content>();
7946  for (ObjectInfo info : childInfos) {
7947  if (null != info.type) {
7948  switch (info.type) {
7949  case VS:
7950  children.add(getVolumeSystemById(info.id, img));
7951  break;
7952  case POOL:
7953  children.add(getPoolById(info.id, img));
7954  break;
7955  case FS:
7956  children.add(getFileSystemById(info.id, img));
7957  break;
7958  case ABSTRACTFILE:
7959  AbstractFile f = getAbstractFileById(info.id);
7960  if (f != null) {
7961  children.add(f);
7962  }
7963  break;
7964  case ARTIFACT:
7965  BlackboardArtifact art = getArtifactById(info.id);
7966  if (art != null) {
7967  children.add(art);
7968  }
7969  break;
7970  case REPORT:
7971  // Do nothing for now - see JIRA-3673
7972  break;
7973  default:
7974  throw new TskCoreException("Image has child of invalid type: " + info.type);
7975  }
7976  }
7977  }
7978  return children;
7979  }
7980 
7991  List<Long> getImageChildrenIds(Image img) throws TskCoreException {
7992  Collection<ObjectInfo> childInfos = getChildrenInfo(img);
7993  List<Long> children = new ArrayList<Long>();
7994  for (ObjectInfo info : childInfos) {
7995  if (info.type == ObjectType.VS
7996  || info.type == ObjectType.POOL
7997  || info.type == ObjectType.FS
7998  || info.type == ObjectType.ABSTRACTFILE
7999  || info.type == ObjectType.ARTIFACT) {
8000  children.add(info.id);
8001  } else if (info.type == ObjectType.REPORT) {
8002  // Do nothing for now - see JIRA-3673
8003  } else {
8004  throw new TskCoreException("Image has child of invalid type: " + info.type);
8005  }
8006  }
8007  return children;
8008  }
8009 
8020  List<Content> getPoolChildren(Pool pool) throws TskCoreException {
8021  Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
8022  List<Content> children = new ArrayList<Content>();
8023  for (ObjectInfo info : childInfos) {
8024  if (null != info.type) {
8025  switch (info.type) {
8026  case VS:
8027  children.add(getVolumeSystemById(info.id, pool));
8028  break;
8029  case ABSTRACTFILE:
8030  AbstractFile f = getAbstractFileById(info.id);
8031  if (f != null) {
8032  children.add(f);
8033  }
8034  break;
8035  case ARTIFACT:
8036  BlackboardArtifact art = getArtifactById(info.id);
8037  if (art != null) {
8038  children.add(art);
8039  }
8040  break;
8041  default:
8042  throw new TskCoreException("Pool has child of invalid type: " + info.type);
8043  }
8044  }
8045  }
8046  return children;
8047  }
8048 
8059  List<Long> getPoolChildrenIds(Pool pool) throws TskCoreException {
8060  Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
8061  List<Long> children = new ArrayList<Long>();
8062  for (ObjectInfo info : childInfos) {
8063  if (info.type == ObjectType.VS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
8064  children.add(info.id);
8065  } else {
8066  throw new TskCoreException("Pool has child of invalid type: " + info.type);
8067  }
8068  }
8069  return children;
8070  }
8071 
8082  List<Content> getVolumeSystemChildren(VolumeSystem vs) throws TskCoreException {
8083  Collection<ObjectInfo> childInfos = getChildrenInfo(vs);
8084  List<Content> children = new ArrayList<Content>();
8085  for (ObjectInfo info : childInfos) {
8086  if (null != info.type) {
8087  switch (info.type) {
8088  case VOL:
8089  children.add(getVolumeById(info.id, vs));
8090  break;
8091  case ABSTRACTFILE:
8092  AbstractFile f = getAbstractFileById(info.id);
8093  if (f != null) {
8094  children.add(f);
8095  }
8096  break;
8097  case ARTIFACT:
8098  BlackboardArtifact art = getArtifactById(info.id);
8099  if (art != null) {
8100  children.add(art);
8101  }
8102  break;
8103  default:
8104  throw new TskCoreException("VolumeSystem has child of invalid type: " + info.type);
8105  }
8106  }
8107  }
8108  return children;
8109  }
8110 
8121  List<Long> getVolumeSystemChildrenIds(VolumeSystem vs) throws TskCoreException {
8122  Collection<ObjectInfo> childInfos = getChildrenInfo(vs);
8123  List<Long> children = new ArrayList<Long>();
8124  for (ObjectInfo info : childInfos) {
8125  if (info.type == ObjectType.VOL || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
8126  children.add(info.id);
8127  } else {
8128  throw new TskCoreException("VolumeSystem has child of invalid type: " + info.type);
8129  }
8130  }
8131  return children;
8132  }
8133 
8144  List<Content> getVolumeChildren(Volume vol) throws TskCoreException {
8145  Collection<ObjectInfo> childInfos = getChildrenInfo(vol);
8146  List<Content> children = new ArrayList<Content>();
8147  for (ObjectInfo info : childInfos) {
8148  if (null != info.type) {
8149  switch (info.type) {
8150  case POOL:
8151  children.add(getPoolById(info.id, vol));
8152  break;
8153  case FS:
8154  children.add(getFileSystemById(info.id, vol));
8155  break;
8156  case ABSTRACTFILE:
8157  AbstractFile f = getAbstractFileById(info.id);
8158  if (f != null) {
8159  children.add(f);
8160  }
8161  break;
8162  case ARTIFACT:
8163  BlackboardArtifact art = getArtifactById(info.id);
8164  if (art != null) {
8165  children.add(art);
8166  }
8167  break;
8168  default:
8169  throw new TskCoreException("Volume has child of invalid type: " + info.type);
8170  }
8171  }
8172  }
8173  return children;
8174  }
8175 
8186  List<Long> getVolumeChildrenIds(Volume vol) throws TskCoreException {
8187  final Collection<ObjectInfo> childInfos = getChildrenInfo(vol);
8188  final List<Long> children = new ArrayList<Long>();
8189  for (ObjectInfo info : childInfos) {
8190  if (info.type == ObjectType.FS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
8191  children.add(info.id);
8192  } else {
8193  throw new TskCoreException("Volume has child of invalid type: " + info.type);
8194  }
8195  }
8196  return children;
8197  }
8198 
8212  public Image addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone) throws TskCoreException {
8213  long imageId = this.caseHandle.addImageInfo(deviceObjId, imageFilePaths, timeZone, this);
8214  return getImageById(imageId);
8215  }
8216 
8226  public Map<Long, List<String>> getImagePaths() throws TskCoreException {
8227  CaseDbConnection connection = connections.getConnection();
8229  Statement s1 = null;
8230  Statement s2 = null;
8231  ResultSet rs1 = null;
8232  ResultSet rs2 = null;
8233  try {
8234  s1 = connection.createStatement();
8235  rs1 = connection.executeQuery(s1, "SELECT obj_id FROM tsk_image_info"); //NON-NLS
8236  s2 = connection.createStatement();
8237  Map<Long, List<String>> imgPaths = new LinkedHashMap<Long, List<String>>();
8238  while (rs1.next()) {
8239  long obj_id = rs1.getLong("obj_id"); //NON-NLS
8240  rs2 = connection.executeQuery(s2, "SELECT * FROM tsk_image_names WHERE obj_id = " + obj_id); //NON-NLS
8241  List<String> paths = new ArrayList<String>();
8242  while (rs2.next()) {
8243  paths.add(rs2.getString("name"));
8244  }
8245  rs2.close();
8246  rs2 = null;
8247  imgPaths.put(obj_id, paths);
8248  }
8249  return imgPaths;
8250  } catch (SQLException ex) {
8251  throw new TskCoreException("Error getting image paths.", ex);
8252  } finally {
8253  closeResultSet(rs2);
8254  closeStatement(s2);
8255  closeResultSet(rs1);
8256  closeStatement(s1);
8257  connection.close();
8259  }
8260  }
8261 
8272  private List<String> getImagePathsById(long objectId) throws TskCoreException {
8273  List<String> imagePaths = new ArrayList<String>();
8274  CaseDbConnection connection = connections.getConnection();
8276  Statement statement = null;
8277  ResultSet resultSet = null;
8278  try {
8279  statement = connection.createStatement();
8280  resultSet = connection.executeQuery(statement, "SELECT name FROM tsk_image_names WHERE tsk_image_names.obj_id = " + objectId); //NON-NLS
8281  while (resultSet.next()) {
8282  imagePaths.add(resultSet.getString("name"));
8283  }
8284  } catch (SQLException ex) {
8285  throw new TskCoreException(String.format("Error getting image names with obj_id = %d", objectId), ex);
8286  } finally {
8287  closeResultSet(resultSet);
8288  closeStatement(statement);
8289  connection.close();
8291  }
8292 
8293  return imagePaths;
8294  }
8295 
8302  public List<Image> getImages() throws TskCoreException {
8303  CaseDbConnection connection = connections.getConnection();
8305  Statement s = null;
8306  ResultSet rs = null;
8307  try {
8308  s = connection.createStatement();
8309  rs = connection.executeQuery(s, "SELECT obj_id FROM tsk_image_info"); //NON-NLS
8310  Collection<Long> imageIDs = new ArrayList<Long>();
8311  while (rs.next()) {
8312  imageIDs.add(rs.getLong("obj_id")); //NON-NLS
8313  }
8314  List<Image> images = new ArrayList<Image>();
8315  for (long id : imageIDs) {
8316  images.add(getImageById(id));
8317  }
8318  return images;
8319  } catch (SQLException ex) {
8320  throw new TskCoreException("Error retrieving images.", ex);
8321  } finally {
8322  closeResultSet(rs);
8323  closeStatement(s);
8324  connection.close();
8326  }
8327  }
8328 
8339  public void setImagePaths(long obj_id, List<String> paths) throws TskCoreException {
8340  CaseDbConnection connection = connections.getConnection();
8342  PreparedStatement statement = null;
8343  try {
8344  connection.beginTransaction();
8345  statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_IMAGE_NAME);
8346  statement.clearParameters();
8347  statement.setLong(1, obj_id);
8348  connection.executeUpdate(statement);
8349  for (int i = 0; i < paths.size(); i++) {
8350  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
8351  statement.clearParameters();
8352  statement.setLong(1, obj_id);
8353  statement.setString(2, paths.get(i));
8354  statement.setLong(3, i);
8355  connection.executeUpdate(statement);
8356  }
8357  connection.commitTransaction();
8358  } catch (SQLException ex) {
8359  connection.rollbackTransaction();
8360  throw new TskCoreException("Error updating image paths.", ex);
8361  } finally {
8362  connection.close();
8364  }
8365  }
8366 
8378  void deleteDataSource(long dataSourceObjectId) throws TskCoreException {
8379  CaseDbConnection connection = connections.getConnection();
8380  Statement statement = null;
8382  try {
8383  statement = connection.createStatement();
8384  connection.beginTransaction();
8385  // The following delete(s) uses a foreign key delete with cascade in the DB so that it will delete
8386  // all associated rows from tsk_object and its children. For large data sources this may take some time.
8387  statement.execute("DELETE FROM tsk_objects WHERE obj_id = " + dataSourceObjectId);
8388  // The following delete uses a foreign key delete with cascade in the DB so that it will delete all
8389  // associated rows from accounts table and its children.
8390  String accountSql = "DELETE FROM accounts WHERE account_id in (SELECT account_id FROM accounts "
8391  + "WHERE account_id NOT IN (SELECT account1_id FROM account_relationships) "
8392  + "AND account_id NOT IN (SELECT account2_id FROM account_relationships))";
8393  statement.execute(accountSql);
8394  connection.commitTransaction();
8395  } catch (SQLException ex) {
8396  connection.rollbackTransaction();
8397  throw new TskCoreException("Error deleting data source.", ex);
8398  } finally {
8399  connection.close();
8401  }
8402  }
8403 
8429  private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnection connection) throws SQLException {
8430  ArrayList<AbstractFile> results = new ArrayList<AbstractFile>();
8431  try {
8432  while (rs.next()) {
8433  final short type = rs.getShort("type"); //NON-NLS
8434  if (type == TSK_DB_FILES_TYPE_ENUM.FS.getFileType()
8435  && (rs.getShort("meta_type") != TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue())) {
8436  FsContent result;
8437  if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()) { //NON-NLS
8438  result = directory(rs, null);
8439  } else {
8440  result = file(rs, null);
8441  }
8442  results.add(result);
8443  } else if (type == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
8444  || (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue())) { //NON-NLS
8445  final VirtualDirectory virtDir = virtualDirectory(rs, connection);
8446  results.add(virtDir);
8447  } else if (type == TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR.getFileType()) {
8448  final LocalDirectory localDir = localDirectory(rs);
8449  results.add(localDir);
8450  } else if (type == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
8451  || type == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
8452  || type == TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()
8453  || type == TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType()) {
8454  TSK_DB_FILES_TYPE_ENUM atype = TSK_DB_FILES_TYPE_ENUM.valueOf(type);
8455  String parentPath = rs.getString("parent_path"); //NON-NLS
8456  if (parentPath == null) {
8457  parentPath = "/"; //NON-NLS
8458  }
8459  LayoutFile lf = new LayoutFile(this,
8460  rs.getLong("obj_id"), //NON-NLS
8461  rs.getLong("data_source_obj_id"),
8462  rs.getString("name"), //NON-NLS
8463  atype,
8464  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8465  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
8466  rs.getLong("size"), //NON-NLS
8467  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8468  rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type")); //NON-NLS
8469  results.add(lf);
8470  } else if (type == TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()) {
8471  final DerivedFile df;
8472  df = derivedFile(rs, connection, AbstractContent.UNKNOWN_ID);
8473  results.add(df);
8474  } else if (type == TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()) {
8475  final LocalFile lf;
8476  lf = localFile(rs, connection, AbstractContent.UNKNOWN_ID);
8477  results.add(lf);
8478  } else if (type == TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()) {
8479  final SlackFile sf = slackFile(rs, null);
8480  results.add(sf);
8481  }
8482  } //end for each resultSet
8483  } catch (SQLException e) {
8484  logger.log(Level.SEVERE, "Error getting abstract files from result set", e); //NON-NLS
8485  }
8486 
8487  return results;
8488  }
8489 
8490  // This following methods generate AbstractFile objects from a ResultSet
8502  org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLException {
8503  org.sleuthkit.datamodel.File f = new org.sleuthkit.datamodel.File(this, rs.getLong("obj_id"), //NON-NLS
8504  rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
8505  TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
8506  rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
8507  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8508  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8509  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8510  rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
8511  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8512  (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
8513  rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8514  rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension")); //NON-NLS
8515  f.setFileSystem(fs);
8516  return f;
8517  }
8518 
8530  Directory directory(ResultSet rs, FileSystem fs) throws SQLException {
8531  Directory dir = new Directory(this, rs.getLong("obj_id"), rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
8532  TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
8533  rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
8534  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8535  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8536  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8537  rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
8538  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8539  rs.getShort("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
8540  rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8541  rs.getString("parent_path")); //NON-NLS
8542  dir.setFileSystem(fs);
8543  return dir;
8544  }
8545 
8556  VirtualDirectory virtualDirectory(ResultSet rs, CaseDbConnection connection) throws SQLException {
8557  String parentPath = rs.getString("parent_path"); //NON-NLS
8558  if (parentPath == null) {
8559  parentPath = "";
8560  }
8561 
8562  long objId = rs.getLong("obj_id");
8563  long dsObjId = rs.getLong("data_source_obj_id");
8564  if (objId == dsObjId) { // virtual directory is a data source
8565 
8566  String deviceId = "";
8567  String timeZone = "";
8568  Statement s = null;
8569  ResultSet rsDataSourceInfo = null;
8570 
8572  try {
8573  s = connection.createStatement();
8574  rsDataSourceInfo = connection.executeQuery(s, "SELECT device_id, time_zone FROM data_source_info WHERE obj_id = " + objId);
8575  if (rsDataSourceInfo.next()) {
8576  deviceId = rsDataSourceInfo.getString("device_id");
8577  timeZone = rsDataSourceInfo.getString("time_zone");
8578  }
8579  } catch (SQLException ex) {
8580  logger.log(Level.SEVERE, "Error data source info for datasource id " + objId, ex); //NON-NLS
8581  } finally {
8582  closeResultSet(rsDataSourceInfo);
8583  closeStatement(s);
8585  }
8586 
8587  return new LocalFilesDataSource(this,
8588  objId, dsObjId,
8589  deviceId,
8590  rs.getString("name"),
8591  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8592  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8593  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")),
8594  rs.getShort("meta_flags"),
8595  timeZone,
8596  rs.getString("md5"),
8597  FileKnown.valueOf(rs.getByte("known")),
8598  parentPath);
8599  } else {
8600  final VirtualDirectory vd = new VirtualDirectory(this,
8601  objId, dsObjId,
8602  rs.getString("name"), //NON-NLS
8603  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8604  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8605  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8606  rs.getShort("meta_flags"), rs.getString("md5"), //NON-NLS
8607  FileKnown.valueOf(rs.getByte("known")), parentPath); //NON-NLS
8608  return vd;
8609  }
8610  }
8611 
8621  LocalDirectory localDirectory(ResultSet rs) throws SQLException {
8622  String parentPath = rs.getString("parent_path"); //NON-NLS
8623  if (parentPath == null) {
8624  parentPath = "";
8625  }
8626  final LocalDirectory ld = new LocalDirectory(this, rs.getLong("obj_id"), //NON-NLS
8627  rs.getLong("data_source_obj_id"), rs.getString("name"), //NON-NLS
8628  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8629  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8630  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8631  rs.getShort("meta_flags"), rs.getString("md5"), //NON-NLS
8632  FileKnown.valueOf(rs.getByte("known")), parentPath); //NON-NLS
8633  return ld;
8634  }
8635 
8649  private DerivedFile derivedFile(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
8650  boolean hasLocalPath = rs.getBoolean("has_path"); //NON-NLS
8651  long objId = rs.getLong("obj_id"); //NON-NLS
8652  String localPath = null;
8653  TskData.EncodingType encodingType = TskData.EncodingType.NONE;
8654  if (hasLocalPath) {
8655  ResultSet rsFilePath = null;
8657  try {
8658  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE);
8659  statement.clearParameters();
8660  statement.setLong(1, objId);
8661  rsFilePath = connection.executeQuery(statement);
8662  if (rsFilePath.next()) {
8663  localPath = rsFilePath.getString("path");
8664  encodingType = TskData.EncodingType.valueOf(rsFilePath.getInt("encoding_type"));
8665  }
8666  } catch (SQLException ex) {
8667  logger.log(Level.SEVERE, "Error getting encoding type for file " + objId, ex); //NON-NLS
8668  } finally {
8669  closeResultSet(rsFilePath);
8671  }
8672  }
8673  String parentPath = rs.getString("parent_path"); //NON-NLS
8674  if (parentPath == null) {
8675  parentPath = "";
8676  }
8677  final DerivedFile df = new DerivedFile(this, objId, rs.getLong("data_source_obj_id"),
8678  rs.getString("name"), //NON-NLS
8679  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8680  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8681  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
8682  rs.getLong("size"), //NON-NLS
8683  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8684  rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8685  parentPath, localPath, parentId, rs.getString("mime_type"),
8686  encodingType, rs.getString("extension"));
8687  return df;
8688  }
8689 
8703  private LocalFile localFile(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
8704  long objId = rs.getLong("obj_id"); //NON-NLS
8705  String localPath = null;
8706  TskData.EncodingType encodingType = TskData.EncodingType.NONE;
8707  if (rs.getBoolean("has_path")) {
8708  ResultSet rsFilePath = null;
8710  try {
8711  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE);
8712  statement.clearParameters();
8713  statement.setLong(1, objId);
8714  rsFilePath = connection.executeQuery(statement);
8715  if (rsFilePath.next()) {
8716  localPath = rsFilePath.getString("path");
8717  encodingType = TskData.EncodingType.valueOf(rsFilePath.getInt("encoding_type"));
8718  }
8719  } catch (SQLException ex) {
8720  logger.log(Level.SEVERE, "Error getting encoding type for file " + objId, ex); //NON-NLS
8721  } finally {
8722  closeResultSet(rsFilePath);
8724  }
8725  }
8726  String parentPath = rs.getString("parent_path"); //NON-NLS
8727  if (null == parentPath) {
8728  parentPath = "";
8729  }
8730  LocalFile file = new LocalFile(this, objId, rs.getString("name"), //NON-NLS
8731  TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type")), //NON-NLS
8732  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8733  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8734  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
8735  rs.getLong("size"), //NON-NLS
8736  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8737  rs.getString("mime_type"), rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8738  parentId, parentPath, rs.getLong("data_source_obj_id"),
8739  localPath, encodingType, rs.getString("extension"));
8740  return file;
8741  }
8742 
8754  org.sleuthkit.datamodel.SlackFile slackFile(ResultSet rs, FileSystem fs) throws SQLException {
8755  org.sleuthkit.datamodel.SlackFile f = new org.sleuthkit.datamodel.SlackFile(this, rs.getLong("obj_id"), //NON-NLS
8756  rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
8757  TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
8758  rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
8759  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8760  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8761  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8762  rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
8763  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8764  (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
8765  rs.getString("md5"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8766  rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension")); //NON-NLS
8767  f.setFileSystem(fs);
8768  return f;
8769  }
8770 
8782  List<Content> fileChildren(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
8783  List<Content> children = new ArrayList<Content>();
8784 
8785  while (rs.next()) {
8786  TskData.TSK_DB_FILES_TYPE_ENUM type = TskData.TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type"));
8787 
8788  if (null != type) {
8789  switch (type) {
8790  case FS:
8791  if (rs.getShort("meta_type") != TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()) {
8792  FsContent result;
8793  if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()) {
8794  result = directory(rs, null);
8795  } else {
8796  result = file(rs, null);
8797  }
8798  children.add(result);
8799  } else {
8800  VirtualDirectory virtDir = virtualDirectory(rs, connection);
8801  children.add(virtDir);
8802  }
8803  break;
8804  case VIRTUAL_DIR:
8805  VirtualDirectory virtDir = virtualDirectory(rs, connection);
8806  children.add(virtDir);
8807  break;
8808  case LOCAL_DIR:
8809  LocalDirectory localDir = localDirectory(rs);
8810  children.add(localDir);
8811  break;
8812  case UNALLOC_BLOCKS:
8813  case UNUSED_BLOCKS:
8814  case CARVED:
8815  case LAYOUT_FILE: {
8816  String parentPath = rs.getString("parent_path");
8817  if (parentPath == null) {
8818  parentPath = "";
8819  }
8820  final LayoutFile lf = new LayoutFile(this, rs.getLong("obj_id"),
8821  rs.getLong("data_source_obj_id"), rs.getString("name"), type,
8822  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")),
8823  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")),
8824  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"),
8825  rs.getLong("size"),
8826  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"),
8827  rs.getString("md5"),
8828  FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type"));
8829  children.add(lf);
8830  break;
8831  }
8832  case DERIVED:
8833  final DerivedFile df = derivedFile(rs, connection, parentId);
8834  children.add(df);
8835  break;
8836  case LOCAL: {
8837  final LocalFile lf = localFile(rs, connection, parentId);
8838  children.add(lf);
8839  break;
8840  }
8841  case SLACK: {
8842  final SlackFile sf = slackFile(rs, null);
8843  children.add(sf);
8844  break;
8845  }
8846  default:
8847  break;
8848  }
8849  }
8850  }
8851  return children;
8852  }
8853 
8869  private List<BlackboardArtifact> resultSetToArtifacts(ResultSet rs) throws SQLException, TskCoreException {
8870  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
8871  try {
8872  while (rs.next()) {
8873  BlackboardArtifact.Type artifactType = getArtifactType(rs.getInt("artifact_type_id"));
8874  if (artifactType != null) {
8875  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
8876  rs.getInt("artifact_type_id"), artifactType.getTypeName(), artifactType.getDisplayName(),
8877  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
8878  } else {
8879  throw new TskCoreException("Error looking up artifact type ID " + rs.getInt("artifact_type_id") + " from artifact " + rs.getLong("artifact_id"));
8880  }
8881  } //end for each resultSet
8882  } catch (SQLException e) {
8883  logger.log(Level.SEVERE, "Error getting artifacts from result set", e); //NON-NLS
8884  }
8885 
8886  return artifacts;
8887  }
8888 
8910  public CaseDbQuery executeQuery(String query) throws TskCoreException {
8911  return new CaseDbQuery(query);
8912  }
8913 
8935  public CaseDbQuery executeInsertOrUpdate(String query) throws TskCoreException {
8936  return new CaseDbQuery(query, true);
8937  }
8938 
8946  CaseDbConnection getConnection() throws TskCoreException {
8947  return connections.getConnection();
8948  }
8949 
8950  synchronized String getUniqueCaseIdentifier() throws TskCoreException {
8951  if (caseHandle != null) {
8952  return caseHandle.getCaseDbIdentifier();
8953  }
8954  throw new TskCoreException("Case has been closed");
8955  }
8956 
8957  @Override
8958  protected void finalize() throws Throwable {
8959  try {
8960  close();
8961  } finally {
8962  super.finalize();
8963  }
8964  }
8965 
8969  public synchronized void close() {
8971 
8972  try {
8973  connections.close();
8974  } catch (TskCoreException ex) {
8975  logger.log(Level.SEVERE, "Error closing database connection pool.", ex); //NON-NLS
8976  }
8977 
8978  fileSystemIdMap.clear();
8979 
8980  try {
8981  if (this.caseHandle != null) {
8982  this.caseHandle.free();
8983  this.caseHandle = null;
8984  }
8985  } catch (TskCoreException ex) {
8986  logger.log(Level.SEVERE, "Error freeing case handle.", ex); //NON-NLS
8987  } finally {
8989  }
8990  }
8991 
9004  public boolean setKnown(AbstractFile file, FileKnown fileKnown) throws TskCoreException {
9005  long id = file.getId();
9006  FileKnown currentKnown = file.getKnown();
9007  if (currentKnown.compareTo(fileKnown) > 0) {
9008  return false;
9009  }
9010  CaseDbConnection connection = connections.getConnection();
9012  Statement statement = null;
9013  try {
9014  statement = connection.createStatement();
9015  connection.executeUpdate(statement, "UPDATE tsk_files " //NON-NLS
9016  + "SET known='" + fileKnown.getFileKnownValue() + "' " //NON-NLS
9017  + "WHERE obj_id=" + id); //NON-NLS
9018 
9019  file.setKnown(fileKnown);
9020  } catch (SQLException ex) {
9021  throw new TskCoreException("Error setting Known status.", ex);
9022  } finally {
9023  closeStatement(statement);
9024  connection.close();
9026  }
9027  return true;
9028  }
9029 
9038  void setFileName(String name, long objId) throws TskCoreException {
9039 
9040  CaseDbConnection connection = connections.getConnection();
9042  try {
9043  PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_FILE_NAME);
9044  preparedStatement.clearParameters();
9045  preparedStatement.setString(1, name);
9046  preparedStatement.setLong(2, objId);
9047  connection.executeUpdate(preparedStatement);
9048  } catch (SQLException ex) {
9049  throw new TskCoreException(String.format("Error updating while the name for object ID %d to %s", objId, name), ex);
9050  } finally {
9051  connection.close();
9053  }
9054  }
9055 
9064  void setImageName(String name, long objId) throws TskCoreException {
9065 
9066  CaseDbConnection connection = connections.getConnection();
9068  try {
9069  PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_IMAGE_NAME);
9070  preparedStatement.clearParameters();
9071  preparedStatement.setString(1, name);
9072  preparedStatement.setLong(2, objId);
9073  connection.executeUpdate(preparedStatement);
9074  } catch (SQLException ex) {
9075  throw new TskCoreException(String.format("Error updating while the name for object ID %d to %s", objId, name), ex);
9076  } finally {
9077  connection.close();
9079  }
9080  }
9081 
9091  public void setFileMIMEType(AbstractFile file, String mimeType) throws TskCoreException {
9092  CaseDbConnection connection = connections.getConnection();
9093  Statement statement = null;
9094  ResultSet rs = null;
9096  try {
9097  statement = connection.createStatement();
9098  connection.executeUpdate(statement, String.format("UPDATE tsk_files SET mime_type = '%s' WHERE obj_id = %d", mimeType, file.getId()));
9099  file.setMIMEType(mimeType);
9100  } catch (SQLException ex) {
9101  throw new TskCoreException(String.format("Error setting MIME type for file (obj_id = %s)", file.getId()), ex);
9102  } finally {
9103  closeResultSet(rs);
9104  closeStatement(statement);
9105  connection.close();
9107  }
9108  }
9109 
9119  void setMd5Hash(AbstractFile file, String md5Hash) throws TskCoreException {
9120  if (md5Hash == null) {
9121  return;
9122  }
9123  long id = file.getId();
9124  CaseDbConnection connection = connections.getConnection();
9126  try {
9127  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_FILE_MD5);
9128  statement.clearParameters();
9129  statement.setString(1, md5Hash.toLowerCase());
9130  statement.setLong(2, id);
9131  connection.executeUpdate(statement);
9132  file.setMd5Hash(md5Hash.toLowerCase());
9133  } catch (SQLException ex) {
9134  throw new TskCoreException("Error setting MD5 hash", ex);
9135  } finally {
9136  connection.close();
9138  }
9139  }
9140 
9150  void setMd5ImageHash(Image img, String md5Hash) throws TskCoreException {
9151  if (md5Hash == null) {
9152  return;
9153  }
9154  long id = img.getId();
9155  CaseDbConnection connection = connections.getConnection();
9157  try {
9158  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_MD5);
9159  statement.clearParameters();
9160  statement.setString(1, md5Hash.toLowerCase());
9161  statement.setLong(2, id);
9162  connection.executeUpdate(statement);
9163  } catch (SQLException ex) {
9164  throw new TskCoreException("Error setting MD5 hash", ex);
9165  } finally {
9166  connection.close();
9168  }
9169  }
9170 
9181  String getMd5ImageHash(Image img) throws TskCoreException {
9182  long id = img.getId();
9183  CaseDbConnection connection = connections.getConnection();
9185  ResultSet rs = null;
9186  String hash = "";
9187  try {
9188  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_MD5);
9189  statement.clearParameters();
9190  statement.setLong(1, id);
9191  rs = connection.executeQuery(statement);
9192  if (rs.next()) {
9193  hash = rs.getString("md5");
9194  }
9195  return hash;
9196  } catch (SQLException ex) {
9197  throw new TskCoreException("Error getting MD5 hash", ex);
9198  } finally {
9199  closeResultSet(rs);
9200  connection.close();
9202  }
9203  }
9204 
9214  void setSha1ImageHash(Image img, String sha1Hash) throws TskCoreException {
9215  if (sha1Hash == null) {
9216  return;
9217  }
9218  long id = img.getId();
9219  CaseDbConnection connection = connections.getConnection();
9221  try {
9222  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_SHA1);
9223  statement.clearParameters();
9224  statement.setString(1, sha1Hash.toLowerCase());
9225  statement.setLong(2, id);
9226  connection.executeUpdate(statement);
9227  } catch (SQLException ex) {
9228  throw new TskCoreException("Error setting SHA1 hash", ex);
9229  } finally {
9230  connection.close();
9232  }
9233  }
9234 
9245  String getSha1ImageHash(Image img) throws TskCoreException {
9246  long id = img.getId();
9247  CaseDbConnection connection = connections.getConnection();
9249  ResultSet rs = null;
9250  String hash = "";
9251  try {
9252  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_SHA1);
9253  statement.clearParameters();
9254  statement.setLong(1, id);
9255  rs = connection.executeQuery(statement);
9256  if (rs.next()) {
9257  hash = rs.getString("sha1");
9258  }
9259  return hash;
9260  } catch (SQLException ex) {
9261  throw new TskCoreException("Error getting SHA1 hash", ex);
9262  } finally {
9263  closeResultSet(rs);
9264  connection.close();
9266  }
9267  }
9268 
9278  void setSha256ImageHash(Image img, String sha256Hash) throws TskCoreException {
9279  if (sha256Hash == null) {
9280  return;
9281  }
9282  long id = img.getId();
9283  CaseDbConnection connection = connections.getConnection();
9285  try {
9286  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_SHA256);
9287  statement.clearParameters();
9288  statement.setString(1, sha256Hash.toLowerCase());
9289  statement.setLong(2, id);
9290  connection.executeUpdate(statement);
9291  } catch (SQLException ex) {
9292  throw new TskCoreException("Error setting SHA256 hash", ex);
9293  } finally {
9294  connection.close();
9296  }
9297  }
9298 
9309  String getSha256ImageHash(Image img) throws TskCoreException {
9310  long id = img.getId();
9311  CaseDbConnection connection = connections.getConnection();
9313  ResultSet rs = null;
9314  String hash = "";
9315  try {
9316  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_SHA256);
9317  statement.clearParameters();
9318  statement.setLong(1, id);
9319  rs = connection.executeQuery(statement);
9320  if (rs.next()) {
9321  hash = rs.getString("sha256");
9322  }
9323  return hash;
9324  } catch (SQLException ex) {
9325  throw new TskCoreException("Error setting SHA256 hash", ex);
9326  } finally {
9327  closeResultSet(rs);
9328  connection.close();
9330  }
9331  }
9332 
9341  void setAcquisitionDetails(DataSource datasource, String details) throws TskCoreException {
9342 
9343  long id = datasource.getId();
9344  CaseDbConnection connection = connections.getConnection();
9346  try {
9347  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
9348  statement.clearParameters();
9349  statement.setString(1, details);
9350  statement.setLong(2, id);
9351  connection.executeUpdate(statement);
9352  } catch (SQLException ex) {
9353  throw new TskCoreException("Error setting acquisition details", ex);
9354  } finally {
9355  connection.close();
9357  }
9358  }
9359 
9369  void setAcquisitionDetails(long dataSourceId, String details, CaseDbTransaction trans) throws TskCoreException {
9371  try {
9372  CaseDbConnection connection = trans.getConnection();
9373  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
9374  statement.clearParameters();
9375  statement.setString(1, details);
9376  statement.setLong(2, dataSourceId);
9377  connection.executeUpdate(statement);
9378  } catch (SQLException ex) {
9379  throw new TskCoreException("Error setting acquisition details", ex);
9380  } finally {
9382  }
9383  }
9384 
9394  String getAcquisitionDetails(DataSource datasource) throws TskCoreException {
9395  long id = datasource.getId();
9396  CaseDbConnection connection = connections.getConnection();
9398  ResultSet rs = null;
9399  String hash = "";
9400  try {
9401  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ACQUISITION_DETAILS);
9402  statement.clearParameters();
9403  statement.setLong(1, id);
9404  rs = connection.executeQuery(statement);
9405  if (rs.next()) {
9406  hash = rs.getString("acquisition_details");
9407  }
9408  return hash;
9409  } catch (SQLException ex) {
9410  throw new TskCoreException("Error setting acquisition details", ex);
9411  } finally {
9412  closeResultSet(rs);
9413  connection.close();
9415  }
9416  }
9417 
9428  public void setReviewStatus(BlackboardArtifact artifact, BlackboardArtifact.ReviewStatus newStatus) throws TskCoreException {
9429  if (newStatus == null) {
9430  return;
9431  }
9432  CaseDbConnection connection = connections.getConnection();
9434  Statement statement = null;
9435  try {
9436  statement = connection.createStatement();
9437  connection.executeUpdate(statement, "UPDATE blackboard_artifacts "
9438  + " SET review_status_id=" + newStatus.getID()
9439  + " WHERE blackboard_artifacts.artifact_id = " + artifact.getArtifactID());
9440  } catch (SQLException ex) {
9441  throw new TskCoreException("Error setting review status", ex);
9442  } finally {
9443  closeStatement(statement);
9444  connection.close();
9446  }
9447  }
9448 
9459  public int countFsContentType(TskData.TSK_FS_META_TYPE_ENUM contentType) throws TskCoreException {
9460  CaseDbConnection connection = connections.getConnection();
9462  Statement s = null;
9463  ResultSet rs = null;
9464  try {
9465  s = connection.createStatement();
9466  Short contentShort = contentType.getValue();
9467  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files WHERE meta_type = '" + contentShort.toString() + "'"); //NON-NLS
9468  int count = 0;
9469  if (rs.next()) {
9470  count = rs.getInt("count");
9471  }
9472  return count;
9473  } catch (SQLException ex) {
9474  throw new TskCoreException("Error getting number of objects.", ex);
9475  } finally {
9476  closeResultSet(rs);
9477  closeStatement(s);
9478  connection.close();
9480  }
9481  }
9482 
9491  public static String escapeSingleQuotes(String text) {
9492  String escapedText = null;
9493  if (text != null) {
9494  escapedText = text.replaceAll("'", "''");
9495  }
9496  return escapedText;
9497  }
9498 
9506  public List<AbstractFile> findFilesByMd5(String md5Hash) {
9507  if (md5Hash == null) {
9508  return Collections.<AbstractFile>emptyList();
9509  }
9510  CaseDbConnection connection;
9511  try {
9512  connection = connections.getConnection();
9513  } catch (TskCoreException ex) {
9514  logger.log(Level.SEVERE, "Error finding files by md5 hash " + md5Hash, ex); //NON-NLS
9515  return Collections.<AbstractFile>emptyList();
9516  }
9518  Statement s = null;
9519  ResultSet rs = null;
9520  try {
9521  s = connection.createStatement();
9522  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " //NON-NLS
9523  + " md5 = '" + md5Hash.toLowerCase() + "' " //NON-NLS
9524  + "AND size > 0"); //NON-NLS
9525  return resultSetToAbstractFiles(rs, connection);
9526  } catch (SQLException ex) {
9527  logger.log(Level.WARNING, "Error querying database.", ex); //NON-NLS
9528  return Collections.<AbstractFile>emptyList();
9529  } finally {
9530  closeResultSet(rs);
9531  closeStatement(s);
9532  connection.close();
9534  }
9535  }
9536 
9543  public boolean allFilesMd5Hashed() {
9544  CaseDbConnection connection;
9545  try {
9546  connection = connections.getConnection();
9547  } catch (TskCoreException ex) {
9548  logger.log(Level.SEVERE, "Error checking md5 hashing status", ex); //NON-NLS
9549  return false;
9550  }
9551  boolean allFilesAreHashed = false;
9553  Statement s = null;
9554  ResultSet rs = null;
9555  try {
9556  s = connection.createStatement();
9557  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files " //NON-NLS
9558  + "WHERE dir_type = '" + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + "' " //NON-NLS
9559  + "AND md5 IS NULL " //NON-NLS
9560  + "AND size > '0'"); //NON-NLS
9561  if (rs.next() && rs.getInt("count") == 0) {
9562  allFilesAreHashed = true;
9563  }
9564  } catch (SQLException ex) {
9565  logger.log(Level.WARNING, "Failed to query whether all files have MD5 hashes", ex); //NON-NLS
9566  } finally {
9567  closeResultSet(rs);
9568  closeStatement(s);
9569  connection.close();
9571  }
9572  return allFilesAreHashed;
9573  }
9574 
9580  public int countFilesMd5Hashed() {
9581  CaseDbConnection connection;
9582  try {
9583  connection = connections.getConnection();
9584  } catch (TskCoreException ex) {
9585  logger.log(Level.SEVERE, "Error getting database connection for hashed files count", ex); //NON-NLS
9586  return 0;
9587  }
9588  int count = 0;
9590  Statement s = null;
9591  ResultSet rs = null;
9592  try {
9593  s = connection.createStatement();
9594  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files " //NON-NLS
9595  + "WHERE md5 IS NOT NULL " //NON-NLS
9596  + "AND size > '0'"); //NON-NLS
9597  if (rs.next()) {
9598  count = rs.getInt("count");
9599  }
9600  } catch (SQLException ex) {
9601  logger.log(Level.WARNING, "Failed to query for all the files.", ex); //NON-NLS
9602  } finally {
9603  closeResultSet(rs);
9604  closeStatement(s);
9605  connection.close();
9607  }
9608  return count;
9609 
9610  }
9611 
9620  public List<TagName> getAllTagNames() throws TskCoreException {
9621  CaseDbConnection connection = connections.getConnection();
9623  ResultSet resultSet = null;
9624  try {
9625  // SELECT * FROM tag_names
9626  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES);
9627  resultSet = connection.executeQuery(statement);
9628  ArrayList<TagName> tagNames = new ArrayList<>();
9629  while (resultSet.next()) {
9630  tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9631  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9632  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
9633  }
9634  return tagNames;
9635  } catch (SQLException ex) {
9636  throw new TskCoreException("Error selecting rows from tag_names table", ex);
9637  } finally {
9638  closeResultSet(resultSet);
9639  connection.close();
9641  }
9642  }
9643 
9654  public List<TagName> getTagNamesInUse() throws TskCoreException {
9655  CaseDbConnection connection = connections.getConnection();
9657  ResultSet resultSet = null;
9658  try {
9659  // SELECT * FROM tag_names WHERE tag_name_id IN (SELECT tag_name_id from content_tags UNION SELECT tag_name_id FROM blackboard_artifact_tags)
9660  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES_IN_USE);
9661  resultSet = connection.executeQuery(statement);
9662  ArrayList<TagName> tagNames = new ArrayList<>();
9663  while (resultSet.next()) {
9664  tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9665  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9666  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
9667  }
9668  return tagNames;
9669  } catch (SQLException ex) {
9670  throw new TskCoreException("Error selecting rows from tag_names table", ex);
9671  } finally {
9672  closeResultSet(resultSet);
9673  connection.close();
9675  }
9676  }
9677 
9690  public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
9691 
9692  ArrayList<TagName> tagNames = new ArrayList<TagName>();
9693  // SELECT * FROM tag_names WHERE tag_name_id IN
9694  // ( SELECT content_tags.tag_name_id as tag_name_id FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id AND tsk_files.data_source_obj_id = ? "
9695  // UNION
9696  // SELECT artifact_tags.tag_name_id as tag_name_id FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts WHERE artifact_tags.artifact_id = arts.artifact_id AND arts.data_source_obj_id = ? )
9697  // )
9698  CaseDbConnection connection = connections.getConnection();
9700  ResultSet resultSet = null;
9701 
9702  try {
9703  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES_IN_USE_BY_DATASOURCE);
9704  statement.setLong(1, dsObjId);
9705  statement.setLong(2, dsObjId);
9706  resultSet = connection.executeQuery(statement); //NON-NLS
9707  while (resultSet.next()) {
9708  tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9709  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9710  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
9711  }
9712  return tagNames;
9713  } catch (SQLException ex) {
9714  throw new TskCoreException("Failed to get tag names in use for data source objID : " + dsObjId, ex);
9715  } finally {
9716  closeResultSet(resultSet);
9717  connection.close();
9719  }
9720  }
9721 
9735  @Deprecated
9736  public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TskCoreException {
9737  return addOrUpdateTagName(displayName, description, color, TskData.FileKnown.UNKNOWN);
9738  }
9739 
9754  public TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TskCoreException {
9755  CaseDbConnection connection = connections.getConnection();
9757  ResultSet resultSet = null;
9758  try {
9759  PreparedStatement statement;
9760  // INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?) ON CONFLICT (display_name) DO UPDATE SET description = ?, color = ?, knownStatus = ?
9761  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OR_UPDATE_TAG_NAME, Statement.RETURN_GENERATED_KEYS);
9762  statement.clearParameters();
9763  statement.setString(5, description);
9764  statement.setString(6, color.getName());
9765  statement.setByte(7, knownStatus.getFileKnownValue());
9766  statement.setString(1, displayName);
9767  statement.setString(2, description);
9768  statement.setString(3, color.getName());
9769  statement.setByte(4, knownStatus.getFileKnownValue());
9770  connection.executeUpdate(statement);
9771  resultSet = statement.getGeneratedKeys();
9772  resultSet.next();
9773 
9774  long tagId = resultSet.getLong(1);
9775 
9776  resultSet.close();
9777  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAME_BY_ID);
9778  statement.clearParameters();
9779  statement.setLong(1, tagId);
9780  resultSet = connection.executeQuery(statement);
9781  resultSet.next();
9782 
9783  return new TagName(tagId, displayName, description, color, knownStatus, resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
9784 
9785  } catch (SQLException ex) {
9786  throw new TskCoreException("Error adding row for " + displayName + " tag name to tag_names table", ex);
9787  } finally {
9788  closeResultSet(resultSet);
9789  connection.close();
9791  }
9792  }
9793 
9808  @Deprecated
9809  public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
9810  return taggingMgr.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset).getAddedTag();
9811  }
9812 
9813  /*
9814  * Deletes a row from the content_tags table in the case database. @param
9815  * tag A ContentTag data transfer object (DTO) for the row to delete.
9816  * @throws TskCoreException
9817  */
9818  public void deleteContentTag(ContentTag tag) throws TskCoreException {
9819  CaseDbConnection connection = connections.getConnection();
9821  try {
9822  // DELETE FROM content_tags WHERE tag_id = ?
9823  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_CONTENT_TAG);
9824  statement.clearParameters();
9825  statement.setLong(1, tag.getId());
9826  connection.executeUpdate(statement);
9827  } catch (SQLException ex) {
9828  throw new TskCoreException("Error deleting row from content_tags table (id = " + tag.getId() + ")", ex);
9829  } finally {
9830  connection.close();
9832  }
9833  }
9834 
9843  public List<ContentTag> getAllContentTags() throws TskCoreException {
9844  CaseDbConnection connection = connections.getConnection();
9846  ResultSet resultSet = null;
9847  try {
9848  // SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
9849  // FROM content_tags
9850  // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
9851  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
9852  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS);
9853  resultSet = connection.executeQuery(statement);
9854  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
9855  while (resultSet.next()) {
9856  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9857  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9858  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
9859  Content content = getContentById(resultSet.getLong("obj_id")); //NON-NLS
9860  tags.add(new ContentTag(resultSet.getLong("tag_id"), content, tagName, resultSet.getString("comment"),
9861  resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"))); //NON-NLS
9862  }
9863  return tags;
9864  } catch (SQLException ex) {
9865  throw new TskCoreException("Error selecting rows from content_tags table", ex);
9866  } finally {
9867  closeResultSet(resultSet);
9868  connection.close();
9870  }
9871  }
9872 
9883  public long getContentTagsCountByTagName(TagName tagName) throws TskCoreException {
9884  if (tagName.getId() == Tag.ID_NOT_SET) {
9885  throw new TskCoreException("TagName object is invalid, id not set");
9886  }
9887  CaseDbConnection connection = connections.getConnection();
9889  ResultSet resultSet = null;
9890  try {
9891  // SELECT COUNT(*) AS count FROM content_tags WHERE tag_name_id = ?
9892  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CONTENT_TAGS_BY_TAG_NAME);
9893  statement.clearParameters();
9894  statement.setLong(1, tagName.getId());
9895  resultSet = connection.executeQuery(statement);
9896  if (resultSet.next()) {
9897  return resultSet.getLong("count");
9898  } else {
9899  throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")");
9900  }
9901  } catch (SQLException ex) {
9902  throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")", ex);
9903  } finally {
9904  closeResultSet(resultSet);
9905  connection.close();
9907  }
9908  }
9909 
9925  public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
9926 
9927  if (tagName.getId() == Tag.ID_NOT_SET) {
9928  throw new TskCoreException("TagName object is invalid, id not set");
9929  }
9930 
9931  CaseDbConnection connection = connections.getConnection();
9933  ResultSet resultSet = null;
9934  try {
9935  // "SELECT COUNT(*) AS count FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id"
9936  // + " AND content_tags.tag_name_id = ? "
9937  // + " AND tsk_files.data_source_obj_id = ? "
9938  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
9939  statement.clearParameters();
9940  statement.setLong(1, tagName.getId());
9941  statement.setLong(2, dsObjId);
9942 
9943  resultSet = connection.executeQuery(statement);
9944  if (resultSet.next()) {
9945  return resultSet.getLong("count");
9946  } else {
9947  throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")" + " for dsObjId = " + dsObjId);
9948  }
9949  } catch (SQLException ex) {
9950  throw new TskCoreException("Failed to get content_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
9951  } finally {
9952  closeResultSet(resultSet);
9953  connection.close();
9955  }
9956  }
9957 
9968  public ContentTag getContentTagByID(long contentTagID) throws TskCoreException {
9969 
9970  CaseDbConnection connection = connections.getConnection();
9972  ResultSet resultSet = null;
9973  ContentTag tag = null;
9974  try {
9975  // SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
9976  // FROM content_tags
9977  // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
9978  // UTER LEFT JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
9979  // WHERE tag_id = ?
9980  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAG_BY_ID);
9981  statement.clearParameters();
9982  statement.setLong(1, contentTagID);
9983  resultSet = connection.executeQuery(statement);
9984 
9985  while (resultSet.next()) {
9986  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9987  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9988  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
9989  tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")), tagName,
9990  resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"));
9991  }
9992  resultSet.close();
9993 
9994  } catch (SQLException ex) {
9995  throw new TskCoreException("Error getting content tag with id = " + contentTagID, ex);
9996  } finally {
9997  closeResultSet(resultSet);
9998  connection.close();
10000  }
10001  return tag;
10002  }
10003 
10015  public List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException {
10016  if (tagName.getId() == Tag.ID_NOT_SET) {
10017  throw new TskCoreException("TagName object is invalid, id not set");
10018  }
10019  CaseDbConnection connection = connections.getConnection();
10021  ResultSet resultSet = null;
10022  try {
10023  // SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tsk_examiners.login_name
10024  // FROM content_tags
10025  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10026  // WHERE tag_name_id = ?
10027  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_TAG_NAME);
10028  statement.clearParameters();
10029  statement.setLong(1, tagName.getId());
10030  resultSet = connection.executeQuery(statement);
10031  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
10032  while (resultSet.next()) {
10033  ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")),
10034  tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
10035  tags.add(tag);
10036  }
10037  resultSet.close();
10038  return tags;
10039  } catch (SQLException ex) {
10040  throw new TskCoreException("Error getting content_tags rows (tag_name_id = " + tagName.getId() + ")", ex);
10041  } finally {
10042  closeResultSet(resultSet);
10043  connection.close();
10045  }
10046  }
10047 
10060  public List<ContentTag> getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10061 
10062  CaseDbConnection connection = connections.getConnection();
10064  ResultSet resultSet = null;
10065  try {
10066 
10067  // SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
10068  // FROM content_tags as content_tags, tsk_files as tsk_files
10069  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10070  // WHERE content_tags.obj_id = tsk_files.obj_id
10071  // AND content_tags.tag_name_id = ?
10072  // AND tsk_files.data_source_obj_id = ?
10073  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
10074  statement.clearParameters();
10075  statement.setLong(1, tagName.getId());
10076  statement.setLong(2, dsObjId);
10077  resultSet = connection.executeQuery(statement);
10078  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
10079  while (resultSet.next()) {
10080  ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")),
10081  tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
10082  tags.add(tag);
10083  }
10084  resultSet.close();
10085  return tags;
10086  } catch (SQLException ex) {
10087  throw new TskCoreException("Failed to get content_tags row count for tag_name_id = " + tagName.getId() + " data source objID : " + dsObjId, ex);
10088  } finally {
10089  closeResultSet(resultSet);
10090  connection.close();
10092  }
10093  }
10094 
10106  public List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException {
10107  CaseDbConnection connection = connections.getConnection();
10109  ResultSet resultSet = null;
10110  try {
10111  // SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
10112  // FROM content_tags
10113  // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
10114  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10115  // WHERE content_tags.obj_id = ?
10116  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_CONTENT);
10117  statement.clearParameters();
10118  statement.setLong(1, content.getId());
10119  resultSet = connection.executeQuery(statement);
10120  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
10121  while (resultSet.next()) {
10122  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10123  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10124  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
10125  ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), content, tagName,
10126  resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
10127  tags.add(tag);
10128  }
10129  return tags;
10130  } catch (SQLException ex) {
10131  throw new TskCoreException("Error getting content tags data for content (obj_id = " + content.getId() + ")", ex);
10132  } finally {
10133  closeResultSet(resultSet);
10134  connection.close();
10136  }
10137  }
10138 
10153  @Deprecated
10154  public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
10155  return taggingMgr.addArtifactTag(artifact, tagName, comment).getAddedTag();
10156  }
10157 
10158  /*
10159  * Deletes a row from the blackboard_artifact_tags table in the case
10160  * database. @param tag A BlackboardArtifactTag data transfer object (DTO)
10161  * representing the row to delete. @throws TskCoreException
10162  */
10163  public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
10164  CaseDbConnection connection = connections.getConnection();
10166  try {
10167  // DELETE FROM blackboard_artifact_tags WHERE tag_id = ?
10168  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_ARTIFACT_TAG);
10169  statement.clearParameters();
10170  statement.setLong(1, tag.getId());
10171  connection.executeUpdate(statement);
10172  } catch (SQLException ex) {
10173  throw new TskCoreException("Error deleting row from blackboard_artifact_tags table (id = " + tag.getId() + ")", ex);
10174  } finally {
10175  connection.close();
10177  }
10178  }
10179 
10189  public List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException {
10190  CaseDbConnection connection = connections.getConnection();
10192  ResultSet resultSet = null;
10193  try {
10194  // SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
10195  // FROM blackboard_artifact_tags
10196  // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
10197  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10198  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS);
10199  resultSet = connection.executeQuery(statement);
10200  ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
10201  while (resultSet.next()) {
10202  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10203  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10204  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
10205  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10206  Content content = getContentById(artifact.getObjectID());
10207  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10208  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10209  tags.add(tag);
10210  }
10211  return tags;
10212  } catch (SQLException ex) {
10213  throw new TskCoreException("Error selecting rows from blackboard_artifact_tags table", ex);
10214  } finally {
10215  closeResultSet(resultSet);
10216  connection.close();
10218  }
10219  }
10220 
10231  public long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException {
10232  if (tagName.getId() == Tag.ID_NOT_SET) {
10233  throw new TskCoreException("TagName object is invalid, id not set");
10234  }
10235  CaseDbConnection connection = connections.getConnection();
10237  ResultSet resultSet = null;
10238  try {
10239  // SELECT COUNT(*) AS count FROM blackboard_artifact_tags WHERE tag_name_id = ?
10240  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_TAG_NAME);
10241  statement.clearParameters();
10242  statement.setLong(1, tagName.getId());
10243  resultSet = connection.executeQuery(statement);
10244  if (resultSet.next()) {
10245  return resultSet.getLong("count");
10246  } else {
10247  throw new TskCoreException("Error getting blackboard_artifact_tags row count for tag name (tag_name_id = " + tagName.getId() + ")");
10248  }
10249  } catch (SQLException ex) {
10250  throw new TskCoreException("Error getting blackboard artifact_content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")", ex);
10251  } finally {
10252  closeResultSet(resultSet);
10253  connection.close();
10255  }
10256  }
10257 
10272  public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10273 
10274  if (tagName.getId() == Tag.ID_NOT_SET) {
10275  throw new TskCoreException("TagName object is invalid, id not set");
10276  }
10277 
10278  CaseDbConnection connection = connections.getConnection();
10280  ResultSet resultSet = null;
10281  try {
10282  // "SELECT COUNT(*) AS count FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts WHERE artifact_tags.artifact_id = arts.artifact_id"
10283  // + " AND artifact_tags.tag_name_id = ?"
10284  // + " AND arts.data_source_obj_id = ? "
10285  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_TAG_NAME_BY_DATASOURCE);
10286  statement.clearParameters();
10287  statement.setLong(1, tagName.getId());
10288  statement.setLong(2, dsObjId);
10289  resultSet = connection.executeQuery(statement);
10290  if (resultSet.next()) {
10291  return resultSet.getLong("count");
10292  } else {
10293  throw new TskCoreException("Error getting blackboard_artifact_tags row count for tag name (tag_name_id = " + tagName.getId() + ")" + " for dsObjId = " + dsObjId);
10294  }
10295  } catch (SQLException ex) {
10296  throw new TskCoreException("Failed to get blackboard_artifact_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
10297  } finally {
10298  closeResultSet(resultSet);
10299  connection.close();
10301  }
10302  }
10303 
10315  public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException {
10316  if (tagName.getId() == Tag.ID_NOT_SET) {
10317  throw new TskCoreException("TagName object is invalid, id not set");
10318  }
10319  CaseDbConnection connection = connections.getConnection();
10321  ResultSet resultSet = null;
10322  try {
10323  // SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tsk_examiners.login_name
10324  // FROM blackboard_artifact_tags
10325  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10326  // WHERE tag_name_id = ?
10327  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_TAG_NAME);
10328  statement.clearParameters();
10329  statement.setLong(1, tagName.getId());
10330  resultSet = connection.executeQuery(statement);
10331  ArrayList<BlackboardArtifactTag> tags = new ArrayList<BlackboardArtifactTag>();
10332  while (resultSet.next()) {
10333  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10334  Content content = getContentById(artifact.getObjectID());
10335  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10336  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10337  tags.add(tag);
10338  }
10339  return tags;
10340  } catch (SQLException ex) {
10341  throw new TskCoreException("Error getting blackboard artifact tags data (tag_name_id = " + tagName.getId() + ")", ex);
10342  } finally {
10343  closeResultSet(resultSet);
10344  connection.close();
10346  }
10347  }
10348 
10363  public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10364 
10365  if (tagName.getId() == Tag.ID_NOT_SET) {
10366  throw new TskCoreException("TagName object is invalid, id not set");
10367  }
10368 
10369  CaseDbConnection connection = connections.getConnection();
10371  ResultSet resultSet = null;
10372  try {
10373  // SELECT artifact_tags.tag_id, artifact_tags.artifact_id, artifact_tags.tag_name_id, artifact_tags.comment, arts.obj_id, arts.artifact_obj_id, arts.data_source_obj_id, arts.artifact_type_id, arts.review_status_id, tsk_examiners.login_name
10374  // FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts
10375  // LEFT OUTER JOIN tsk_examiners ON artifact_tags.examiner_id = tsk_examiners.examiner_id
10376  // WHERE artifact_tags.artifact_id = arts.artifact_id
10377  // AND artifact_tags.tag_name_id = ?
10378  // AND arts.data_source_obj_id = ?
10379  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
10380  statement.clearParameters();
10381  statement.setLong(1, tagName.getId());
10382  statement.setLong(2, dsObjId);
10383  resultSet = connection.executeQuery(statement);
10384  ArrayList<BlackboardArtifactTag> tags = new ArrayList<BlackboardArtifactTag>();
10385  while (resultSet.next()) {
10386  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10387  Content content = getContentById(artifact.getObjectID());
10388  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10389  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10390  tags.add(tag);
10391  }
10392  return tags;
10393  } catch (SQLException ex) {
10394  throw new TskCoreException("Failed to get blackboard_artifact_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
10395  } finally {
10396  closeResultSet(resultSet);
10397  connection.close();
10399  }
10400 
10401  }
10402 
10414  public BlackboardArtifactTag getBlackboardArtifactTagByID(long artifactTagID) throws TskCoreException {
10415 
10416  CaseDbConnection connection = connections.getConnection();
10418  ResultSet resultSet = null;
10419  BlackboardArtifactTag tag = null;
10420  try {
10421  //SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
10422  // FROM blackboard_artifact_tags
10423  // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
10424  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10425  // WHERE blackboard_artifact_tags.tag_id = ?
10426  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAG_BY_ID);
10427  statement.clearParameters();
10428  statement.setLong(1, artifactTagID);
10429  resultSet = connection.executeQuery(statement);
10430 
10431  while (resultSet.next()) {
10432  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10433  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10434  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
10435  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10436  Content content = getContentById(artifact.getObjectID());
10437  tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10438  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name"));
10439  }
10440  resultSet.close();
10441 
10442  } catch (SQLException ex) {
10443  throw new TskCoreException("Error getting blackboard artifact tag with id = " + artifactTagID, ex);
10444  } finally {
10445  closeResultSet(resultSet);
10446  connection.close();
10448  }
10449  return tag;
10450  }
10451 
10464  public List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException {
10465  CaseDbConnection connection = connections.getConnection();
10467  ResultSet resultSet = null;
10468  try {
10469  // SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name
10470  // FROM blackboard_artifact_tags
10471  // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
10472  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10473  // WHERE blackboard_artifact_tags.artifact_id = ?
10474  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_ARTIFACT);
10475  statement.clearParameters();
10476  statement.setLong(1, artifact.getArtifactID());
10477  resultSet = connection.executeQuery(statement);
10478  ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
10479  while (resultSet.next()) {
10480  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10481  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10482  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
10483  Content content = getContentById(artifact.getObjectID());
10484  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10485  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10486  tags.add(tag);
10487  }
10488  return tags;
10489  } catch (SQLException ex) {
10490  throw new TskCoreException("Error getting blackboard artifact tags data (artifact_id = " + artifact.getArtifactID() + ")", ex);
10491  } finally {
10492  closeResultSet(resultSet);
10493  connection.close();
10495  }
10496  }
10497 
10506  public void updateImagePath(String newPath, long objectId) throws TskCoreException {
10507  CaseDbConnection connection = connections.getConnection();
10509  try {
10510  // UPDATE tsk_image_names SET name = ? WHERE obj_id = ?
10511  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_PATH);
10512  statement.clearParameters();
10513  statement.setString(1, newPath);
10514  statement.setLong(2, objectId);
10515  connection.executeUpdate(statement);
10516  } catch (SQLException ex) {
10517  throw new TskCoreException("Error updating image path in database for object " + objectId, ex);
10518  } finally {
10519  connection.close();
10521  }
10522  }
10523 
10537  public Report addReport(String localPath, String sourceModuleName, String reportName) throws TskCoreException {
10538  return addReport(localPath, sourceModuleName, reportName, null);
10539  }
10540 
10556  public Report addReport(String localPath, String sourceModuleName, String reportName, Content parent) throws TskCoreException {
10557  // Make sure the local path of the report is in the database directory
10558  // or one of its subdirectories.
10559  String relativePath = ""; //NON-NLS
10560  long createTime = 0;
10561  String localPathLower = localPath.toLowerCase();
10562 
10563  if (localPathLower.startsWith("http")) {
10564  relativePath = localPathLower;
10565  createTime = System.currentTimeMillis() / 1000;
10566  } else {
10567  /*
10568  * Note: The following call to .relativize() may be dangerous in
10569  * case-sensitive operating systems and should be looked at. For
10570  * now, we are simply relativizing the paths as all lower case, then
10571  * using the length of the result to pull out the appropriate number
10572  * of characters from the localPath String.
10573  */
10574  try {
10575  String casePathLower = getDbDirPath().toLowerCase();
10576  int length = new File(casePathLower).toURI().relativize(new File(localPathLower).toURI()).getPath().length();
10577  relativePath = new File(localPath.substring(localPathLower.length() - length)).getPath();
10578  } catch (IllegalArgumentException ex) {
10579  String errorMessage = String.format("Local path %s not in the database directory or one of its subdirectories", localPath);
10580  throw new TskCoreException(errorMessage, ex);
10581  }
10582  try {
10583  // get its file time
10584  java.io.File tempFile = new java.io.File(localPath);
10585  // Convert to UNIX epoch (seconds, not milliseconds).
10586  createTime = tempFile.lastModified() / 1000;
10587  } catch (Exception ex) {
10588  throw new TskCoreException("Could not get create time for report at " + localPath, ex);
10589  }
10590  }
10591 
10592  // Write the report data to the database.
10593  CaseDbConnection connection = connections.getConnection();
10595  ResultSet resultSet = null;
10596  try {
10597  // Insert a row for the report into the tsk_objects table.
10598  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
10599  long parentObjId = 0;
10600  if (parent != null) {
10601  parentObjId = parent.getId();
10602  }
10603  long objectId = addObject(parentObjId, TskData.ObjectType.REPORT.getObjectType(), connection);
10604 
10605  // INSERT INTO reports (obj_id, path, crtime, src_module_name, display_name) VALUES (?, ?, ?, ?, ?)
10606  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_REPORT);
10607  statement.clearParameters();
10608  statement.setLong(1, objectId);
10609  statement.setString(2, relativePath);
10610  statement.setLong(3, createTime);
10611  statement.setString(4, sourceModuleName);
10612  statement.setString(5, reportName);
10613  connection.executeUpdate(statement);
10614  return new Report(this, objectId, localPath, createTime, sourceModuleName, reportName, parent);
10615  } catch (SQLException ex) {
10616  throw new TskCoreException("Error adding report " + localPath + " to reports table", ex);
10617  } finally {
10618  closeResultSet(resultSet);
10619  connection.close();
10621  }
10622  }
10623 
10632  public List<Report> getAllReports() throws TskCoreException {
10633  CaseDbConnection connection = connections.getConnection();
10635  ResultSet resultSet = null;
10636  ResultSet parentResultSet = null;
10637  PreparedStatement statement = null;
10638  Statement parentStatement = null;
10639  try {
10640  // SELECT * FROM reports
10641  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_REPORTS);
10642  parentStatement = connection.createStatement();
10643  resultSet = connection.executeQuery(statement);
10644  ArrayList<Report> reports = new ArrayList<Report>();
10645  while (resultSet.next()) {
10646  String localpath = resultSet.getString("path");
10647  if (localpath.toLowerCase().startsWith("http") == false) {
10648  // make path absolute
10649  localpath = Paths.get(getDbDirPath(), localpath).normalize().toString(); //NON-NLS
10650  }
10651 
10652  // get the report parent
10653  Content parent = null;
10654  long reportId = resultSet.getLong("obj_id"); // NON-NLS
10655  String parentQuery = String.format("SELECT * FROM tsk_objects WHERE obj_id = %s;", reportId);
10656  parentResultSet = parentStatement.executeQuery(parentQuery);
10657  if (parentResultSet.next()) {
10658  long parentId = parentResultSet.getLong("par_obj_id"); // NON-NLS
10659  parent = this.getContentById(parentId);
10660  }
10661  parentResultSet.close();
10662 
10663  reports.add(new Report(this,
10664  reportId,
10665  localpath,
10666  resultSet.getLong("crtime"), //NON-NLS
10667  resultSet.getString("src_module_name"), //NON-NLS
10668  resultSet.getString("report_name"),
10669  parent)); //NON-NLS
10670  }
10671  return reports;
10672  } catch (SQLException ex) {
10673  throw new TskCoreException("Error querying reports table", ex);
10674  } finally {
10675  closeResultSet(resultSet);
10676  closeResultSet(parentResultSet);
10677  closeStatement(statement);
10678  closeStatement(parentStatement);
10679 
10680  connection.close();
10682  }
10683  }
10684 
10694  public Report getReportById(long id) throws TskCoreException {
10695  CaseDbConnection connection = connections.getConnection();
10697  PreparedStatement statement = null;
10698  Statement parentStatement = null;
10699  ResultSet resultSet = null;
10700  ResultSet parentResultSet = null;
10701  Report report = null;
10702  try {
10703  // SELECT * FROM reports WHERE obj_id = ?
10704  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_REPORT_BY_ID);
10705  parentStatement = connection.createStatement();
10706  statement.clearParameters();
10707  statement.setLong(1, id);
10708  resultSet = connection.executeQuery(statement);
10709 
10710  if (resultSet.next()) {
10711  // get the report parent
10712  Content parent = null;
10713  String parentQuery = String.format("SELECT * FROM tsk_objects WHERE obj_id = %s;", id);
10714  parentResultSet = parentStatement.executeQuery(parentQuery);
10715  if (parentResultSet.next()) {
10716  long parentId = parentResultSet.getLong("par_obj_id"); // NON-NLS
10717  parent = this.getContentById(parentId);
10718  }
10719 
10720  report = new Report(this, resultSet.getLong("obj_id"), //NON-NLS
10721  Paths.get(getDbDirPath(), resultSet.getString("path")).normalize().toString(), //NON-NLS
10722  resultSet.getLong("crtime"), //NON-NLS
10723  resultSet.getString("src_module_name"), //NON-NLS
10724  resultSet.getString("report_name"),
10725  parent); //NON-NLS
10726  } else {
10727  throw new TskCoreException("No report found for id: " + id);
10728  }
10729  } catch (SQLException ex) {
10730  throw new TskCoreException("Error querying reports table for id: " + id, ex);
10731  } finally {
10732  closeResultSet(resultSet);
10733  closeResultSet(parentResultSet);
10734  closeStatement(statement);
10735  closeStatement(parentStatement);
10736  connection.close();
10738  }
10739 
10740  return report;
10741  }
10742 
10750  public void deleteReport(Report report) throws TskCoreException {
10751  CaseDbConnection connection = connections.getConnection();
10753  try {
10754  // DELETE FROM reports WHERE reports.obj_id = ?
10755  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_REPORT);
10756  statement.setLong(1, report.getId());
10757  connection.executeUpdate(statement);
10758  } catch (SQLException ex) {
10759  throw new TskCoreException("Error querying reports table", ex);
10760  } finally {
10761  connection.close();
10763  }
10764  }
10765 
10766  static void closeResultSet(ResultSet resultSet) {
10767  if (resultSet != null) {
10768  try {
10769  resultSet.close();
10770  } catch (SQLException ex) {
10771  logger.log(Level.SEVERE, "Error closing ResultSet", ex); //NON-NLS
10772  }
10773  }
10774  }
10775 
10776  static void closeStatement(Statement statement) {
10777  if (statement != null) {
10778  try {
10779  statement.close();
10780  } catch (SQLException ex) {
10781  logger.log(Level.SEVERE, "Error closing Statement", ex); //NON-NLS
10782 
10783  }
10784  }
10785  }
10786 
10795  void setIngestJobEndDateTime(long ingestJobId, long endDateTime) throws TskCoreException {
10796  CaseDbConnection connection = connections.getConnection();
10798  try {
10799  Statement statement = connection.createStatement();
10800  statement.executeUpdate("UPDATE ingest_jobs SET end_date_time=" + endDateTime + " WHERE ingest_job_id=" + ingestJobId + ";");
10801  } catch (SQLException ex) {
10802  throw new TskCoreException("Error updating the end date (ingest_job_id = " + ingestJobId + ".", ex);
10803  } finally {
10804  connection.close();
10806  }
10807  }
10808 
10809  void setIngestJobStatus(long ingestJobId, IngestJobStatusType status) throws TskCoreException {
10810  CaseDbConnection connection = connections.getConnection();
10812  try {
10813  Statement statement = connection.createStatement();
10814  statement.executeUpdate("UPDATE ingest_jobs SET status_id=" + status.ordinal() + " WHERE ingest_job_id=" + ingestJobId + ";");
10815  } catch (SQLException ex) {
10816  throw new TskCoreException("Error ingest job status (ingest_job_id = " + ingestJobId + ".", ex);
10817  } finally {
10818  connection.close();
10820  }
10821  }
10822 
10839  public final IngestJobInfo addIngestJob(Content dataSource, String hostName, List<IngestModuleInfo> ingestModules, Date jobStart, Date jobEnd, IngestJobStatusType status, String settingsDir) throws TskCoreException {
10840  CaseDbConnection connection = connections.getConnection();
10842  ResultSet resultSet = null;
10843  Statement statement;
10844  try {
10845  connection.beginTransaction();
10846  statement = connection.createStatement();
10847  PreparedStatement insertStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INGEST_JOB, Statement.RETURN_GENERATED_KEYS);
10848  insertStatement.setLong(1, dataSource.getId());
10849  insertStatement.setString(2, hostName);
10850  insertStatement.setLong(3, jobStart.getTime());
10851  insertStatement.setLong(4, jobEnd.getTime());
10852  insertStatement.setInt(5, status.ordinal());
10853  insertStatement.setString(6, settingsDir);
10854  connection.executeUpdate(insertStatement);
10855  resultSet = insertStatement.getGeneratedKeys();
10856  resultSet.next();
10857  long id = resultSet.getLong(1); //last_insert_rowid()
10858  for (int i = 0; i < ingestModules.size(); i++) {
10859  IngestModuleInfo ingestModule = ingestModules.get(i);
10860  statement.executeUpdate("INSERT INTO ingest_job_modules (ingest_job_id, ingest_module_id, pipeline_position) "
10861  + "VALUES (" + id + ", " + ingestModule.getIngestModuleId() + ", " + i + ");");
10862  }
10863  resultSet.close();
10864  resultSet = null;
10865  connection.commitTransaction();
10866  return new IngestJobInfo(id, dataSource.getId(), hostName, jobStart, "", ingestModules, this);
10867  } catch (SQLException ex) {
10868  connection.rollbackTransaction();
10869  throw new TskCoreException("Error adding the ingest job.", ex);
10870  } finally {
10871  closeResultSet(resultSet);
10872  connection.close();
10874  }
10875  }
10876 
10890  public final IngestModuleInfo addIngestModule(String displayName, String factoryClassName, IngestModuleType type, String version) throws TskCoreException {
10891  CaseDbConnection connection = connections.getConnection();
10892  ResultSet resultSet = null;
10893  Statement statement = null;
10894  String uniqueName = factoryClassName + "-" + displayName + "-" + type.toString() + "-" + version;
10896  try {
10897  statement = connection.createStatement();
10898  resultSet = statement.executeQuery("SELECT * FROM ingest_modules WHERE unique_name = '" + uniqueName + "'");
10899  if (!resultSet.next()) {
10900  resultSet.close();
10901  resultSet = null;
10902  PreparedStatement insertStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INGEST_MODULE, Statement.RETURN_GENERATED_KEYS);
10903  insertStatement.setString(1, displayName);
10904  insertStatement.setString(2, uniqueName);
10905  insertStatement.setInt(3, type.ordinal());
10906  insertStatement.setString(4, version);
10907  connection.executeUpdate(insertStatement);
10908  resultSet = statement.getGeneratedKeys();
10909  resultSet.next();
10910  long id = resultSet.getLong(1); //last_insert_rowid()
10911  resultSet.close();
10912  resultSet = null;
10913  return new IngestModuleInfo(id, displayName, uniqueName, type, version);
10914  } else {
10915  return new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
10916  resultSet.getString("unique_name"), IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version"));
10917  }
10918  } catch (SQLException ex) {
10919  try {
10920  closeStatement(statement);
10921  statement = connection.createStatement();
10922  resultSet = statement.executeQuery("SELECT * FROM ingest_modules WHERE unique_name = '" + uniqueName + "'");
10923  if (resultSet.next()) {
10924  return new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
10925  uniqueName, IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version"));
10926  } else {
10927  throw new TskCoreException("Couldn't add new module to database.", ex);
10928  }
10929  } catch (SQLException ex1) {
10930  throw new TskCoreException("Couldn't add new module to database.", ex1);
10931  }
10932  } finally {
10933  closeResultSet(resultSet);
10934  closeStatement(statement);
10935  connection.close();
10937  }
10938  }
10939 
10947  public final List<IngestJobInfo> getIngestJobs() throws TskCoreException {
10948  CaseDbConnection connection = connections.getConnection();
10949  ResultSet resultSet = null;
10950  Statement statement = null;
10951  List<IngestJobInfo> ingestJobs = new ArrayList<IngestJobInfo>();
10953  try {
10954  statement = connection.createStatement();
10955  resultSet = statement.executeQuery("SELECT * FROM ingest_jobs");
10956  while (resultSet.next()) {
10957  ingestJobs.add(new IngestJobInfo(resultSet.getInt("ingest_job_id"), resultSet.getLong("obj_id"),
10958  resultSet.getString("host_name"), new Date(resultSet.getLong("start_date_time")),
10959  new Date(resultSet.getLong("end_date_time")), IngestJobStatusType.fromID(resultSet.getInt("status_id")),
10960  resultSet.getString("settings_dir"), this.getIngestModules(resultSet.getInt("ingest_job_id"), connection), this));
10961  }
10962  return ingestJobs;
10963  } catch (SQLException ex) {
10964  throw new TskCoreException("Couldn't get the ingest jobs.", ex);
10965  } finally {
10966  closeResultSet(resultSet);
10967  closeStatement(statement);
10968  connection.close();
10970  }
10971  }
10972 
10983  private List<IngestModuleInfo> getIngestModules(int ingestJobId, CaseDbConnection connection) throws SQLException {
10984  ResultSet resultSet = null;
10985  Statement statement = null;
10986  List<IngestModuleInfo> ingestModules = new ArrayList<IngestModuleInfo>();
10988  try {
10989  statement = connection.createStatement();
10990  resultSet = statement.executeQuery("SELECT ingest_job_modules.ingest_module_id AS ingest_module_id, "
10991  + "ingest_job_modules.pipeline_position AS pipeline_position, "
10992  + "ingest_modules.display_name AS display_name, ingest_modules.unique_name AS unique_name, "
10993  + "ingest_modules.type_id AS type_id, ingest_modules.version AS version "
10994  + "FROM ingest_job_modules, ingest_modules "
10995  + "WHERE ingest_job_modules.ingest_job_id = " + ingestJobId + " "
10996  + "AND ingest_modules.ingest_module_id = ingest_job_modules.ingest_module_id "
10997  + "ORDER BY (ingest_job_modules.pipeline_position);");
10998  while (resultSet.next()) {
10999  ingestModules.add(new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
11000  resultSet.getString("unique_name"), IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version")));
11001  }
11002  return ingestModules;
11003  } finally {
11004  closeResultSet(resultSet);
11005  closeStatement(statement);
11007 
11008  }
11009  }
11010 
11030  long addImageJNI(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size,
11031  String timezone, String md5, String sha1, String sha256,
11032  String deviceId, String collectionDetails,
11033  CaseDbTransaction transaction) throws TskCoreException {
11035  try {
11036  // Insert a row for the Image into the tsk_objects table.
11037  CaseDbConnection connection = transaction.getConnection();
11038  long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
11039 
11040  // Add a row to tsk_image_info
11041  // INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
11042  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO);
11043  preparedStatement.clearParameters();
11044  preparedStatement.setLong(1, newObjId);
11045  preparedStatement.setShort(2, (short) type.getValue());
11046  preparedStatement.setLong(3, sectorSize);
11047  preparedStatement.setString(4, timezone);
11048  //prevent negative size
11049  long savedSize = size < 0 ? 0 : size;
11050  preparedStatement.setLong(5, savedSize);
11051  preparedStatement.setString(6, md5);
11052  preparedStatement.setString(7, sha1);
11053  preparedStatement.setString(8, sha256);
11054  preparedStatement.setString(9, null);
11055  connection.executeUpdate(preparedStatement);
11056 
11057  // Add a row to data_source_info
11058  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DATA_SOURCE_INFO_WITH_ACQ_DETAIL);
11059  preparedStatement.setLong(1, newObjId);
11060  preparedStatement.setString(2, deviceId);
11061  preparedStatement.setString(3, timezone);
11062  preparedStatement.setString(4, collectionDetails);
11063  connection.executeUpdate(preparedStatement);
11064 
11065  return newObjId;
11066  } catch (SQLException ex) {
11067  throw new TskCoreException(String.format("Error adding image to database"), ex);
11068  } finally {
11070  }
11071  }
11072 
11084  void addImageNameJNI(long objId, String name, long sequence,
11085  CaseDbTransaction transaction) throws TskCoreException {
11087  try {
11088  CaseDbConnection connection = transaction.getConnection();
11089  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
11090  preparedStatement.clearParameters();
11091  preparedStatement.setLong(1, objId);
11092  preparedStatement.setString(2, name);
11093  preparedStatement.setLong(3, sequence);
11094  connection.executeUpdate(preparedStatement);
11095  } catch (SQLException ex) {
11096  throw new TskCoreException(String.format("Error adding image name %s to image with object ID %d", name, objId), ex);
11097  } finally {
11099  }
11100  }
11101 
11144  long addFileJNI(long parentObjId,
11145  Long fsObjId, long dataSourceObjId,
11146  int fsType,
11147  Integer attrType, Integer attrId, String name,
11148  Long metaAddr, Long metaSeq,
11149  int dirType, int metaType, int dirFlags, int metaFlags,
11150  long size,
11151  Long crtime, Long ctime, Long atime, Long mtime,
11152  Integer meta_mode, Integer gid, Integer uid,
11153  String md5, TskData.FileKnown known,
11154  String escaped_path, String extension,
11155  boolean hasLayout, CaseDbTransaction transaction) throws TskCoreException {
11156 
11157  Statement queryStatement = null;
11158  try {
11160  CaseDbConnection connection = transaction.getConnection();
11161 
11162  // Insert a row for the local/logical file into the tsk_objects table.
11163  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
11164  long objectId = addObject(parentObjId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
11165 
11166  // INSERT INTO tsk_files (fs_obj_id, obj_id, data_source_obj_id, type, attr_type, attr_id, name, meta_addr, meta_seq,
11167  // dir_type, meta_type, dir_flags, meta_flags, size, crtime, ctime, atime, mtime,
11168  // mode, gid, uid, md5, known, parent_path, extension)
11169  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_SYSTEM_FILE_All_FIELDS);
11170  statement.clearParameters();
11171  if (fsObjId != null) {
11172  statement.setLong(1, fsObjId); // fs_obj_id
11173  } else {
11174  statement.setNull(1, java.sql.Types.BIGINT);
11175  }
11176  statement.setLong(2, objectId); // obj_id
11177  statement.setLong(3, dataSourceObjId); // data_source_obj_id
11178  statement.setShort(4, (short) fsType); // type
11179  if (attrType != null) {
11180  statement.setShort(5, attrType.shortValue()); // attr_type
11181  } else {
11182  statement.setNull(5, java.sql.Types.SMALLINT);
11183  }
11184  if (attrId != null) {
11185  statement.setInt(6, attrId); // attr_id
11186  } else {
11187  statement.setNull(6, java.sql.Types.INTEGER);
11188  }
11189  statement.setString(7, name); // name
11190  if (metaAddr != null) {
11191  statement.setLong(8, metaAddr); // meta_addr
11192  } else {
11193  statement.setNull(8, java.sql.Types.BIGINT);
11194  }
11195  if (metaSeq != null) {
11196  statement.setInt(9, metaSeq.intValue()); // meta_seq
11197  } else {
11198  statement.setNull(9, java.sql.Types.INTEGER);
11199  }
11200  statement.setShort(10, (short) dirType); // dir_type
11201  statement.setShort(11, (short) metaType); // meta_type
11202  statement.setShort(12, (short) dirFlags); // dir_flags
11203  statement.setShort(13, (short) metaFlags); // meta_flags
11204  statement.setLong(14, size < 0 ? 0 : size); // size
11205  if (crtime != null) {
11206  statement.setLong(15, crtime); // crtime
11207  } else {
11208  statement.setNull(15, java.sql.Types.BIGINT);
11209  }
11210  if (ctime != null) {
11211  statement.setLong(16, ctime); // ctime
11212  } else {
11213  statement.setNull(16, java.sql.Types.BIGINT);
11214  }
11215  if (atime != null) {
11216  statement.setLong(17, atime); // atime
11217  } else {
11218  statement.setNull(17, java.sql.Types.BIGINT);
11219  }
11220  if (mtime != null) {
11221  statement.setLong(18, mtime); // mtime
11222  } else {
11223  statement.setNull(18, java.sql.Types.BIGINT);
11224  }
11225  if (meta_mode != null) {
11226  statement.setLong(19, meta_mode); // mode
11227  } else {
11228  statement.setNull(19, java.sql.Types.BIGINT);
11229  }
11230  if (gid != null) {
11231  statement.setLong(20, gid); // gid
11232  } else {
11233  statement.setNull(20, java.sql.Types.BIGINT);
11234  }
11235  if (uid != null) {
11236  statement.setLong(21, uid); // uid
11237  } else {
11238  statement.setNull(21, java.sql.Types.BIGINT);
11239  }
11240  statement.setString(22, md5); // md5
11241  statement.setInt(23, known.getFileKnownValue());// known
11242  statement.setString(24, escaped_path); // parent_path
11243  statement.setString(25, extension); // extension
11244  if (hasLayout) {
11245  statement.setInt(26, 1); // has_layout
11246  } else {
11247  statement.setNull(26, java.sql.Types.INTEGER);
11248  }
11249  connection.executeUpdate(statement);
11250 
11251  // If this is not a slack file create the timeline events
11252  if (!hasLayout
11253  && TskData.TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType() != fsType
11254  && (!name.equals(".")) && (!name.equals(".."))) {
11255  TimelineManager timelineManager = getTimelineManager();
11256  DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, name,
11257  TSK_FS_NAME_TYPE_ENUM.valueOf((short) dirType),
11258  TSK_FS_META_TYPE_ENUM.valueOf((short) metaType),
11259  TSK_FS_NAME_FLAG_ENUM.valueOf(dirFlags),
11260  (short) metaFlags,
11261  size, ctime, crtime, atime, mtime, null, null, escaped_path, null, parentObjId, null, null, extension);
11262 
11263  timelineManager.addEventsForNewFileQuiet(derivedFile, connection);
11264  }
11265 
11266  return objectId;
11267  } catch (SQLException ex) {
11268  throw new TskCoreException("Failed to add file system file", ex);
11269  } finally {
11270  closeStatement(queryStatement);
11272  }
11273  }
11274 
11287  void addLayoutFileRangeJNI(long objId, long byteStart, long byteLen,
11288  long seq, CaseDbTransaction transaction) throws TskCoreException {
11289  try {
11291  CaseDbConnection connection = transaction.getConnection();
11292 
11293  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
11294  prepStmt.clearParameters();
11295  prepStmt.setLong(1, objId);
11296  prepStmt.setLong(2, byteStart);
11297  prepStmt.setLong(3, byteLen);
11298  prepStmt.setLong(4, seq);
11299  connection.executeUpdate(prepStmt);
11300  } catch (SQLException ex) {
11301  throw new TskCoreException("Error adding layout range to file with obj ID " + objId, ex);
11302  } finally {
11304  }
11305  }
11306 
11310  static class ObjectInfo {
11311 
11312  private long id;
11313  private TskData.ObjectType type;
11314 
11315  ObjectInfo(long id, ObjectType type) {
11316  this.id = id;
11317  this.type = type;
11318  }
11319 
11320  long getId() {
11321  return id;
11322  }
11323 
11324  TskData.ObjectType getType() {
11325  return type;
11326  }
11327  }
11328 
11329  private interface DbCommand {
11330 
11331  void execute() throws SQLException;
11332  }
11333 
11334  private enum PREPARED_STATEMENT {
11335 
11336  SELECT_ARTIFACTS_BY_TYPE("SELECT artifact_id, obj_id FROM blackboard_artifacts " //NON-NLS
11337  + "WHERE artifact_type_id = ?"), //NON-NLS
11338  COUNT_ARTIFACTS_OF_TYPE("SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ? AND review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()), //NON-NLS
11339  COUNT_ARTIFACTS_OF_TYPE_BY_DATA_SOURCE("SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE data_source_obj_id = ? AND artifact_type_id = ? AND review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()), //NON-NLS
11340  COUNT_ARTIFACTS_FROM_SOURCE("SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()), //NON-NLS
11341  COUNT_ARTIFACTS_BY_SOURCE_AND_TYPE("SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND artifact_type_id = ? AND review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()), //NON-NLS
11342  SELECT_FILES_BY_PARENT("SELECT tsk_files.* " //NON-NLS
11343  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11344  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11345  + "WHERE (tsk_objects.par_obj_id = ? ) " //NON-NLS
11346  + "ORDER BY tsk_files.meta_type DESC, LOWER(tsk_files.name)"), //NON-NLS
11347  SELECT_FILES_BY_PARENT_AND_TYPE("SELECT tsk_files.* " //NON-NLS
11348  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11349  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11350  + "WHERE (tsk_objects.par_obj_id = ? AND tsk_files.type = ? ) " //NON-NLS
11351  + "ORDER BY tsk_files.dir_type, LOWER(tsk_files.name)"), //NON-NLS
11352  SELECT_FILE_IDS_BY_PARENT("SELECT tsk_files.obj_id AS obj_id " //NON-NLS
11353  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11354  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11355  + "WHERE (tsk_objects.par_obj_id = ?)"), //NON-NLS
11356  SELECT_FILE_IDS_BY_PARENT_AND_TYPE("SELECT tsk_files.obj_id AS obj_id " //NON-NLS
11357  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11358  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11359  + "WHERE (tsk_objects.par_obj_id = ? " //NON-NLS
11360  + "AND tsk_files.type = ? )"), //NON-NLS
11361  SELECT_FILE_BY_ID("SELECT * FROM tsk_files WHERE obj_id = ? LIMIT 1"), //NON-NLS
11362  SELECT_ARTIFACT_BY_ARTIFACT_OBJ_ID("SELECT * FROM blackboard_artifacts WHERE artifact_obj_id = ? LIMIT 1"),
11363  SELECT_ARTIFACT_BY_ARTIFACT_ID("SELECT * FROM blackboard_artifacts WHERE artifact_id = ? LIMIT 1"),
11364  INSERT_ARTIFACT("INSERT INTO blackboard_artifacts (artifact_id, obj_id, artifact_obj_id, data_source_obj_id, artifact_type_id, review_status_id) " //NON-NLS
11365  + "VALUES (?, ?, ?, ?, ?," + BlackboardArtifact.ReviewStatus.UNDECIDED.getID() + ")"), //NON-NLS
11366  POSTGRESQL_INSERT_ARTIFACT("INSERT INTO blackboard_artifacts (artifact_id, obj_id, artifact_obj_id, data_source_obj_id, artifact_type_id, review_status_id) " //NON-NLS
11367  + "VALUES (DEFAULT, ?, ?, ?, ?," + BlackboardArtifact.ReviewStatus.UNDECIDED.getID() + ")"), //NON-NLS
11368  INSERT_STRING_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_text) " //NON-NLS
11369  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11370  INSERT_BYTE_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_byte) " //NON-NLS
11371  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11372  INSERT_INT_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_int32) " //NON-NLS
11373  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11374  INSERT_LONG_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_int64) " //NON-NLS
11375  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11376  INSERT_DOUBLE_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_double) " //NON-NLS
11377  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11378  SELECT_FILES_BY_DATA_SOURCE_AND_NAME("SELECT * FROM tsk_files WHERE LOWER(name) LIKE LOWER(?) AND LOWER(name) NOT LIKE LOWER('%journal%') AND data_source_obj_id = ?"), //NON-NLS
11379  SELECT_FILES_BY_DATA_SOURCE_AND_PARENT_PATH_AND_NAME("SELECT * FROM tsk_files WHERE LOWER(name) LIKE LOWER(?) AND LOWER(name) NOT LIKE LOWER('%journal%') AND LOWER(parent_path) LIKE LOWER(?) AND data_source_obj_id = ?"), //NON-NLS
11380  UPDATE_FILE_MD5("UPDATE tsk_files SET md5 = ? WHERE obj_id = ?"), //NON-NLS
11381  UPDATE_IMAGE_MD5("UPDATE tsk_image_info SET md5 = ? WHERE obj_id = ?"), //NON-NLS
11382  UPDATE_IMAGE_SHA1("UPDATE tsk_image_info SET sha1 = ? WHERE obj_id = ?"), //NON-NLS
11383  UPDATE_IMAGE_SHA256("UPDATE tsk_image_info SET sha256 = ? WHERE obj_id = ?"), //NON-NLS
11384  SELECT_IMAGE_MD5("SELECT md5 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
11385  SELECT_IMAGE_SHA1("SELECT sha1 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
11386  SELECT_IMAGE_SHA256("SELECT sha256 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
11387  UPDATE_ACQUISITION_DETAILS("UPDATE data_source_info SET acquisition_details = ? WHERE obj_id = ?"), //NON-NLS
11388  SELECT_ACQUISITION_DETAILS("SELECT acquisition_details FROM data_source_info WHERE obj_id = ?"), //NON-NLS
11389  SELECT_LOCAL_PATH_FOR_FILE("SELECT path FROM tsk_files_path WHERE obj_id = ?"), //NON-NLS
11390  SELECT_ENCODING_FOR_FILE("SELECT encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON-NLS
11391  SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE("SELECT path, encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON_NLS
11392  SELECT_PATH_FOR_FILE("SELECT parent_path FROM tsk_files WHERE obj_id = ?"), //NON-NLS
11393  SELECT_FILE_NAME("SELECT name FROM tsk_files WHERE obj_id = ?"), //NON-NLS
11394  SELECT_DERIVED_FILE("SELECT derived_id, rederive FROM tsk_files_derived WHERE obj_id = ?"), //NON-NLS
11395  SELECT_FILE_DERIVATION_METHOD("SELECT tool_name, tool_version, other FROM tsk_files_derived_method WHERE derived_id = ?"), //NON-NLS
11396  SELECT_MAX_OBJECT_ID("SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects"), //NON-NLS
11397  INSERT_OBJECT("INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)"), //NON-NLS
11398  INSERT_FILE("INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id,extension) " //NON-NLS
11399  + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), //NON-NLS
11400  INSERT_FILE_SYSTEM_FILE("INSERT INTO tsk_files(obj_id, fs_obj_id, data_source_obj_id, attr_type, attr_id, name, meta_addr, meta_seq, type, has_path, dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime, atime, mtime, parent_path, extension)"
11401  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), // NON-NLS
11402  INSERT_FILE_SYSTEM_FILE_All_FIELDS("INSERT INTO tsk_files (fs_obj_id, obj_id, data_source_obj_id, type, attr_type, attr_id, name, meta_addr, meta_seq, dir_type, meta_type, dir_flags, meta_flags, size, crtime, ctime, atime, mtime, mode, gid, uid, md5, known, parent_path, extension, has_layout)"
11403  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), // NON-NLS
11404  UPDATE_DERIVED_FILE("UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? "
11405  + "WHERE obj_id = ?"), //NON-NLS
11406  INSERT_LAYOUT_FILE("INSERT INTO tsk_file_layout (obj_id, byte_start, byte_len, sequence) " //NON-NLS
11407  + "VALUES (?, ?, ?, ?)"), //NON-NLS
11408  INSERT_LOCAL_PATH("INSERT INTO tsk_files_path (obj_id, path, encoding_type) VALUES (?, ?, ?)"), //NON-NLS
11409  UPDATE_LOCAL_PATH("UPDATE tsk_files_path SET path = ?, encoding_type = ? WHERE obj_id = ?"), //NON-NLS
11410  COUNT_CHILD_OBJECTS_BY_PARENT("SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?"), //NON-NLS
11411  SELECT_FILE_SYSTEM_BY_OBJECT("SELECT fs_obj_id from tsk_files WHERE obj_id=?"), //NON-NLS
11412  SELECT_TAG_NAMES("SELECT * FROM tag_names"), //NON-NLS
11413  SELECT_TAG_NAMES_IN_USE("SELECT * FROM tag_names " //NON-NLS
11414  + "WHERE tag_name_id IN " //NON-NLS
11415  + "(SELECT tag_name_id from content_tags UNION SELECT tag_name_id FROM blackboard_artifact_tags)"), //NON-NLS
11416  SELECT_TAG_NAMES_IN_USE_BY_DATASOURCE("SELECT * FROM tag_names "
11417  + "WHERE tag_name_id IN "
11418  + "( SELECT content_tags.tag_name_id as tag_name_id "
11419  + "FROM content_tags as content_tags, tsk_files as tsk_files"
11420  + " WHERE content_tags.obj_id = tsk_files.obj_id"
11421  + " AND tsk_files.data_source_obj_id = ?"
11422  + " UNION "
11423  + "SELECT artifact_tags.tag_name_id as tag_name_id "
11424  + " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts "
11425  + " WHERE artifact_tags.artifact_id = arts.artifact_id"
11426  + " AND arts.data_source_obj_id = ?"
11427  + " )"),
11428  INSERT_TAG_NAME("INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?)"), //NON-NLS
11429  INSERT_CONTENT_TAG("INSERT INTO content_tags (obj_id, tag_name_id, comment, begin_byte_offset, end_byte_offset, examiner_id) VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
11430  DELETE_CONTENT_TAG("DELETE FROM content_tags WHERE tag_id = ?"), //NON-NLS
11431  COUNT_CONTENT_TAGS_BY_TAG_NAME("SELECT COUNT(*) AS count FROM content_tags WHERE tag_name_id = ?"), //NON-NLS
11432  COUNT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE(
11433  "SELECT COUNT(*) AS count FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id"
11434  + " AND content_tags.tag_name_id = ? "
11435  + " AND tsk_files.data_source_obj_id = ? "
11436  ),
11437  SELECT_CONTENT_TAGS("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank "
11438  + "FROM content_tags "
11439  + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
11440  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS
11441  SELECT_CONTENT_TAGS_BY_TAG_NAME("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tsk_examiners.login_name "
11442  + "FROM content_tags "
11443  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
11444  + "WHERE tag_name_id = ?"), //NON-NLS
11445  SELECT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id "
11446  + "FROM content_tags as content_tags, tsk_files as tsk_files, tag_names as tag_names, tsk_examiners as tsk_examiners "
11447  + "WHERE content_tags.examiner_id = tsk_examiners.examiner_id"
11448  + " AND content_tags.obj_id = tsk_files.obj_id"
11449  + " AND content_tags.tag_name_id = tag_names.tag_name_id"
11450  + " AND content_tags.tag_name_id = ?"
11451  + " AND tsk_files.data_source_obj_id = ? "),
11452  SELECT_CONTENT_TAG_BY_ID("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank "
11453  + "FROM content_tags "
11454  + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
11455  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
11456  + "WHERE tag_id = ?"), //NON-NLS
11457  SELECT_CONTENT_TAGS_BY_CONTENT("SELECT content_tags.tag_id, content_tags.obj_id, content_tags.tag_name_id, content_tags.comment, content_tags.begin_byte_offset, content_tags.end_byte_offset, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank "
11458  + "FROM content_tags "
11459  + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
11460  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
11461  + "WHERE content_tags.obj_id = ?"), //NON-NLS
11462  INSERT_ARTIFACT_TAG("INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment, examiner_id) "
11463  + "VALUES (?, ?, ?, ?)"), //NON-NLS
11464  DELETE_ARTIFACT_TAG("DELETE FROM blackboard_artifact_tags WHERE tag_id = ?"), //NON-NLS
11465  SELECT_ARTIFACT_TAGS("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tag_names.tag_set_id, tsk_examiners.login_name, tag_names.rank "
11466  + "FROM blackboard_artifact_tags "
11467  + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
11468  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS
11469  COUNT_ARTIFACTS_BY_TAG_NAME("SELECT COUNT(*) AS count FROM blackboard_artifact_tags WHERE tag_name_id = ?"), //NON-NLS
11470  COUNT_ARTIFACTS_BY_TAG_NAME_BY_DATASOURCE("SELECT COUNT(*) AS count FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts WHERE artifact_tags.artifact_id = arts.artifact_id"
11471  + " AND artifact_tags.tag_name_id = ?"
11472  + " AND arts.data_source_obj_id = ? "),
11473  SELECT_ARTIFACT_TAGS_BY_TAG_NAME("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tsk_examiners.login_name "
11474  + "FROM blackboard_artifact_tags "
11475  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
11476  + "WHERE tag_name_id = ?"), //NON-NLS
11477  SELECT_ARTIFACT_TAGS_BY_TAG_NAME_BY_DATASOURCE("SELECT artifact_tags.tag_id, artifact_tags.artifact_id, artifact_tags.tag_name_id, artifact_tags.comment, arts.obj_id, arts.artifact_obj_id, arts.data_source_obj_id, arts.artifact_type_id, arts.review_status_id, tsk_examiners.login_name "
11478  + "FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts, tsk_examiners AS tsk_examiners "
11479  + "WHERE artifact_tags.examiner_id = tsk_examiners.examiner_id"
11480  + " AND artifact_tags.artifact_id = arts.artifact_id"
11481  + " AND artifact_tags.tag_name_id = ? "
11482  + " AND arts.data_source_obj_id = ? "),
11483  SELECT_ARTIFACT_TAG_BY_ID("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank "
11484  + "FROM blackboard_artifact_tags "
11485  + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
11486  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
11487  + "WHERE blackboard_artifact_tags.tag_id = ?"), //NON-NLS
11488  SELECT_ARTIFACT_TAGS_BY_ARTIFACT("SELECT blackboard_artifact_tags.tag_id, blackboard_artifact_tags.artifact_id, blackboard_artifact_tags.tag_name_id, blackboard_artifact_tags.comment, tag_names.display_name, tag_names.description, tag_names.color, tag_names.knownStatus, tsk_examiners.login_name, tag_names.tag_set_id, tag_names.rank "
11489  + "FROM blackboard_artifact_tags "
11490  + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
11491  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
11492  + "WHERE blackboard_artifact_tags.artifact_id = ?"), //NON-NLS
11493  SELECT_REPORTS("SELECT * FROM reports"), //NON-NLS
11494  SELECT_REPORT_BY_ID("SELECT * FROM reports WHERE obj_id = ?"), //NON-NLS
11495  INSERT_REPORT("INSERT INTO reports (obj_id, path, crtime, src_module_name, report_name) VALUES (?, ?, ?, ?, ?)"), //NON-NLS
11496  DELETE_REPORT("DELETE FROM reports WHERE reports.obj_id = ?"), //NON-NLS
11497  INSERT_INGEST_JOB("INSERT INTO ingest_jobs (obj_id, host_name, start_date_time, end_date_time, status_id, settings_dir) VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
11498  INSERT_INGEST_MODULE("INSERT INTO ingest_modules (display_name, unique_name, type_id, version) VALUES(?, ?, ?, ?)"), //NON-NLS
11499  SELECT_ATTR_BY_VALUE_BYTE("SELECT source FROM blackboard_attributes WHERE artifact_id = ? AND attribute_type_id = ? AND value_type = 4 AND value_byte = ?"), //NON-NLS
11500  UPDATE_ATTR_BY_VALUE_BYTE("UPDATE blackboard_attributes SET source = ? WHERE artifact_id = ? AND attribute_type_id = ? AND value_type = 4 AND value_byte = ?"), //NON-NLS
11501  UPDATE_IMAGE_PATH("UPDATE tsk_image_names SET name = ? WHERE obj_id = ?"), // NON-NLS
11502  SELECT_ARTIFACT_OBJECTIDS_BY_PARENT("SELECT blackboard_artifacts.artifact_obj_id AS artifact_obj_id " //NON-NLS
11503  + "FROM tsk_objects INNER JOIN blackboard_artifacts " //NON-NLS
11504  + "ON tsk_objects.obj_id=blackboard_artifacts.obj_id " //NON-NLS
11505  + "WHERE (tsk_objects.par_obj_id = ?)"),
11506  INSERT_OR_UPDATE_TAG_NAME("INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?) ON CONFLICT (display_name) DO UPDATE SET description = ?, color = ?, knownStatus = ?"),
11507  SELECT_EXAMINER_BY_ID("SELECT * FROM tsk_examiners WHERE examiner_id = ?"),
11508  SELECT_EXAMINER_BY_LOGIN_NAME("SELECT * FROM tsk_examiners WHERE login_name = ?"),
11509  INSERT_EXAMINER_POSTGRESQL("INSERT INTO tsk_examiners (login_name) VALUES (?) ON CONFLICT DO NOTHING"),
11510  INSERT_EXAMINER_SQLITE("INSERT OR IGNORE INTO tsk_examiners (login_name) VALUES (?)"),
11511  UPDATE_FILE_NAME("UPDATE tsk_files SET name = ? WHERE obj_id = ?"),
11512  UPDATE_IMAGE_NAME("UPDATE tsk_image_info SET display_name = ? WHERE obj_id = ?"),
11513  DELETE_IMAGE_NAME("DELETE FROM tsk_image_names WHERE obj_id = ?"),
11514  INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"),
11515  INSERT_IMAGE_INFO("INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)"
11516  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"),
11517  INSERT_DATA_SOURCE_INFO("INSERT INTO data_source_info (obj_id, device_id, time_zone) VALUES (?, ?, ?)"),
11518  INSERT_DATA_SOURCE_INFO_WITH_ACQ_DETAIL("INSERT INTO data_source_info (obj_id, device_id, time_zone, acquisition_details) VALUES (?, ?, ?, ?)"),
11519  INSERT_VS_INFO("INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (?, ?, ?, ?)"),
11520  INSERT_VS_PART_SQLITE("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags) VALUES (?, ?, ?, ?, ?, ?)"),
11521  INSERT_VS_PART_POSTGRESQL("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, descr, flags) VALUES (?, ?, ?, ?, ?, ?)"),
11522  INSERT_POOL_INFO("INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)"),
11523  INSERT_FS_INFO("INSERT INTO tsk_fs_info (obj_id, data_source_obj_id, img_offset, fs_type, block_size, block_count, root_inum, first_inum, last_inum, display_name)"
11524  + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"),
11525  SELECT_TAG_NAME_BY_ID("SELECT * FROM tag_names where tag_name_id = ?");
11526 
11527  private final String sql;
11528 
11529  private PREPARED_STATEMENT(String sql) {
11530  this.sql = sql;
11531  }
11532 
11533  String getSQL() {
11534  return sql;
11535  }
11536  }
11537 
11543  abstract private class ConnectionPool {
11544 
11545  private PooledDataSource pooledDataSource;
11546 
11547  public ConnectionPool() {
11548  pooledDataSource = null;
11549  }
11550 
11551  CaseDbConnection getConnection() throws TskCoreException {
11552  if (pooledDataSource == null) {
11553  throw new TskCoreException("Error getting case database connection - case is closed");
11554  }
11555  try {
11556  return getPooledConnection();
11557  } catch (SQLException exp) {
11558  throw new TskCoreException(exp.getMessage());
11559  }
11560  }
11561 
11562  void close() throws TskCoreException {
11563  if (pooledDataSource != null) {
11564  try {
11565  pooledDataSource.close();
11566  } catch (SQLException exp) {
11567  throw new TskCoreException(exp.getMessage());
11568  } finally {
11569  pooledDataSource = null;
11570  }
11571  }
11572  }
11573 
11574  abstract CaseDbConnection getPooledConnection() throws SQLException;
11575 
11576  public PooledDataSource getPooledDataSource() {
11577  return pooledDataSource;
11578  }
11579 
11580  public void setPooledDataSource(PooledDataSource pooledDataSource) {
11581  this.pooledDataSource = pooledDataSource;
11582  }
11583  }
11584 
11589  private final class SQLiteConnections extends ConnectionPool {
11590 
11591  private final Map<String, String> configurationOverrides = new HashMap<String, String>();
11592 
11593  SQLiteConnections(String dbPath) throws SQLException {
11594  configurationOverrides.put("acquireIncrement", "2");
11595  configurationOverrides.put("initialPoolSize", "5");
11596  configurationOverrides.put("minPoolSize", "5");
11597  /*
11598  * NOTE: max pool size and max statements are related. If you
11599  * increase max pool size, then also increase statements.
11600  */
11601  configurationOverrides.put("maxPoolSize", "20");
11602  configurationOverrides.put("maxStatements", "200");
11603  configurationOverrides.put("maxStatementsPerConnection", "20");
11604 
11605  SQLiteConfig config = new SQLiteConfig();
11606  config.setSynchronous(SQLiteConfig.SynchronousMode.OFF); // Reduce I/O operations, we have no OS crash recovery anyway.
11607  config.setReadUncommited(true);
11608  config.enforceForeignKeys(true); // Enforce foreign key constraints.
11609  SQLiteDataSource unpooled = new SQLiteDataSource(config);
11610  unpooled.setUrl("jdbc:sqlite:" + dbPath);
11611  setPooledDataSource((PooledDataSource) DataSources.pooledDataSource(unpooled, configurationOverrides));
11612  }
11613 
11614  @Override
11615  public CaseDbConnection getPooledConnection() throws SQLException {
11616  return new SQLiteConnection(getPooledDataSource().getConnection());
11617  }
11618  }
11619 
11624  private final class PostgreSQLConnections extends ConnectionPool {
11625 
11626  PostgreSQLConnections(String host, int port, String dbName, String userName, String password) throws PropertyVetoException, UnsupportedEncodingException {
11627  ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
11628  comboPooledDataSource.setDriverClass("org.postgresql.Driver"); //loads the jdbc driver
11629  comboPooledDataSource.setJdbcUrl("jdbc:postgresql://" + host + ":" + port + "/"
11630  + URLEncoder.encode(dbName, StandardCharsets.UTF_8.toString()));
11631  comboPooledDataSource.setUser(userName);
11632  comboPooledDataSource.setPassword(password);
11633  comboPooledDataSource.setAcquireIncrement(2);
11634  comboPooledDataSource.setInitialPoolSize(5);
11635  comboPooledDataSource.setMinPoolSize(5);
11636  /*
11637  * NOTE: max pool size and max statements are related. If you
11638  * increase max pool size, then also increase statements.
11639  */
11640  comboPooledDataSource.setMaxPoolSize(20);
11641  comboPooledDataSource.setMaxStatements(200);
11642  comboPooledDataSource.setMaxStatementsPerConnection(20);
11643  setPooledDataSource(comboPooledDataSource);
11644  }
11645 
11646  @Override
11647  public CaseDbConnection getPooledConnection() throws SQLException {
11648  return new PostgreSQLConnection(getPooledDataSource().getConnection());
11649  }
11650  }
11651 
11655  abstract class CaseDbConnection implements AutoCloseable {
11656 
11657  static final int SLEEP_LENGTH_IN_MILLISECONDS = 5000;
11658  static final int MAX_RETRIES = 20; //MAX_RETRIES * SLEEP_LENGTH_IN_MILLESECONDS = max time to hang attempting connection
11659 
11660  private class CreateStatement implements DbCommand {
11661 
11662  private final Connection connection;
11663  private Statement statement = null;
11664 
11665  CreateStatement(Connection connection) {
11666  this.connection = connection;
11667  }
11668 
11669  Statement getStatement() {
11670  return statement;
11671  }
11672 
11673  @Override
11674  public void execute() throws SQLException {
11675  statement = connection.createStatement();
11676  }
11677  }
11678 
11679  private class SetAutoCommit implements DbCommand {
11680 
11681  private final Connection connection;
11682  private final boolean mode;
11683 
11684  SetAutoCommit(Connection connection, boolean mode) {
11685  this.connection = connection;
11686  this.mode = mode;
11687  }
11688 
11689  @Override
11690  public void execute() throws SQLException {
11691  connection.setAutoCommit(mode);
11692  }
11693  }
11694 
11695  private class Commit implements DbCommand {
11696 
11697  private final Connection connection;
11698 
11699  Commit(Connection connection) {
11700  this.connection = connection;
11701  }
11702 
11703  @Override
11704  public void execute() throws SQLException {
11705  connection.commit();
11706  }
11707  }
11708 
11709  private class ExecuteQuery implements DbCommand {
11710 
11711  private final Statement statement;
11712  private final String query;
11713  private ResultSet resultSet;
11714 
11715  ExecuteQuery(Statement statement, String query) {
11716  this.statement = statement;
11717  this.query = query;
11718  }
11719 
11720  ResultSet getResultSet() {
11721  return resultSet;
11722  }
11723 
11724  @Override
11725  public void execute() throws SQLException {
11726  resultSet = statement.executeQuery(query);
11727  }
11728  }
11729 
11730  private class ExecutePreparedStatementQuery implements DbCommand {
11731 
11732  private final PreparedStatement preparedStatement;
11733  private ResultSet resultSet;
11734 
11735  ExecutePreparedStatementQuery(PreparedStatement preparedStatement) {
11736  this.preparedStatement = preparedStatement;
11737  }
11738 
11739  ResultSet getResultSet() {
11740  return resultSet;
11741  }
11742 
11743  @Override
11744  public void execute() throws SQLException {
11745  resultSet = preparedStatement.executeQuery();
11746  }
11747  }
11748 
11749  private class ExecutePreparedStatementUpdate implements DbCommand {
11750 
11751  private final PreparedStatement preparedStatement;
11752 
11753  ExecutePreparedStatementUpdate(PreparedStatement preparedStatement) {
11754  this.preparedStatement = preparedStatement;
11755  }
11756 
11757  @Override
11758  public void execute() throws SQLException {
11759  preparedStatement.executeUpdate();
11760  }
11761  }
11762 
11763  private class ExecuteStatementUpdate implements DbCommand {
11764 
11765  private final Statement statement;
11766  private final String updateCommand;
11767 
11768  ExecuteStatementUpdate(Statement statement, String updateCommand) {
11769  this.statement = statement;
11770  this.updateCommand = updateCommand;
11771  }
11772 
11773  @Override
11774  public void execute() throws SQLException {
11775  statement.executeUpdate(updateCommand);
11776  }
11777  }
11778 
11779  private class ExecuteStatementUpdateGenerateKeys implements DbCommand {
11780 
11781  private final Statement statement;
11782  private final int generateKeys;
11783  private final String updateCommand;
11784 
11785  ExecuteStatementUpdateGenerateKeys(Statement statement, String updateCommand, int generateKeys) {
11786  this.statement = statement;
11787  this.generateKeys = generateKeys;
11788  this.updateCommand = updateCommand;
11789  }
11790 
11791  @Override
11792  public void execute() throws SQLException {
11793  statement.executeUpdate(updateCommand, generateKeys);
11794  }
11795  }
11796 
11797  private class PrepareStatement implements DbCommand {
11798 
11799  private final Connection connection;
11800  private final String input;
11801  private PreparedStatement preparedStatement = null;
11802 
11803  PrepareStatement(Connection connection, String input) {
11804  this.connection = connection;
11805  this.input = input;
11806  }
11807 
11808  PreparedStatement getPreparedStatement() {
11809  return preparedStatement;
11810  }
11811 
11812  @Override
11813  public void execute() throws SQLException {
11814  preparedStatement = connection.prepareStatement(input);
11815  }
11816  }
11817 
11818  private class PrepareStatementGenerateKeys implements DbCommand {
11819 
11820  private final Connection connection;
11821  private final String input;
11822  private final int generateKeys;
11823  private PreparedStatement preparedStatement = null;
11824 
11825  PrepareStatementGenerateKeys(Connection connection, String input, int generateKeysInput) {
11826  this.connection = connection;
11827  this.input = input;
11828  this.generateKeys = generateKeysInput;
11829  }
11830 
11831  PreparedStatement getPreparedStatement() {
11832  return preparedStatement;
11833  }
11834 
11835  @Override
11836  public void execute() throws SQLException {
11837  preparedStatement = connection.prepareStatement(input, generateKeys);
11838  }
11839  }
11840 
11841  abstract void executeCommand(DbCommand command) throws SQLException;
11842 
11843  private final Connection connection;
11844  private final Map<PREPARED_STATEMENT, PreparedStatement> preparedStatements;
11845 
11846  CaseDbConnection(Connection connection) {
11847  this.connection = connection;
11848  preparedStatements = new EnumMap<PREPARED_STATEMENT, PreparedStatement>(PREPARED_STATEMENT.class);
11849  }
11850 
11851  boolean isOpen() {
11852  return this.connection != null;
11853  }
11854 
11855  PreparedStatement getPreparedStatement(PREPARED_STATEMENT statementKey) throws SQLException {
11856  return getPreparedStatement(statementKey, Statement.NO_GENERATED_KEYS);
11857  }
11858 
11859  PreparedStatement getPreparedStatement(PREPARED_STATEMENT statementKey, int generateKeys) throws SQLException {
11860  // Lazy statement preparation.
11861  PreparedStatement statement;
11862  if (this.preparedStatements.containsKey(statementKey)) {
11863  statement = this.preparedStatements.get(statementKey);
11864  } else {
11865  statement = prepareStatement(statementKey.getSQL(), generateKeys);
11866  this.preparedStatements.put(statementKey, statement);
11867  }
11868  return statement;
11869  }
11870 
11871  PreparedStatement prepareStatement(String sqlStatement, int generateKeys) throws SQLException {
11872  PrepareStatement prepareStatement = new PrepareStatement(this.getConnection(), sqlStatement);
11873  executeCommand(prepareStatement);
11874  return prepareStatement.getPreparedStatement();
11875  }
11876 
11877  Statement createStatement() throws SQLException {
11878  CreateStatement createStatement = new CreateStatement(this.connection);
11879  executeCommand(createStatement);
11880  return createStatement.getStatement();
11881  }
11882 
11883  void beginTransaction() throws SQLException {
11884  SetAutoCommit setAutoCommit = new SetAutoCommit(connection, false);
11885  executeCommand(setAutoCommit);
11886  }
11887 
11888  void commitTransaction() throws SQLException {
11889  Commit commit = new Commit(connection);
11890  executeCommand(commit);
11891  // You must turn auto commit back on when done with the transaction.
11892  SetAutoCommit setAutoCommit = new SetAutoCommit(connection, true);
11893  executeCommand(setAutoCommit);
11894  }
11895 
11901  void rollbackTransaction() {
11902  try {
11903  connection.rollback();
11904  } catch (SQLException e) {
11905  logger.log(Level.SEVERE, "Error rolling back transaction", e);
11906  }
11907  try {
11908  connection.setAutoCommit(true);
11909  } catch (SQLException e) {
11910  logger.log(Level.SEVERE, "Error restoring auto-commit", e);
11911  }
11912  }
11913 
11921  void rollbackTransactionWithThrow() throws SQLException {
11922  try {
11923  connection.rollback();
11924  } finally {
11925  connection.setAutoCommit(true);
11926  }
11927  }
11928 
11929  ResultSet executeQuery(Statement statement, String query) throws SQLException {
11930  ExecuteQuery queryCommand = new ExecuteQuery(statement, query);
11931  executeCommand(queryCommand);
11932  return queryCommand.getResultSet();
11933  }
11934 
11944  ResultSet executeQuery(PreparedStatement statement) throws SQLException {
11945  ExecutePreparedStatementQuery executePreparedStatementQuery = new ExecutePreparedStatementQuery(statement);
11946  executeCommand(executePreparedStatementQuery);
11947  return executePreparedStatementQuery.getResultSet();
11948  }
11949 
11950  void executeUpdate(Statement statement, String update) throws SQLException {
11951  executeUpdate(statement, update, Statement.NO_GENERATED_KEYS);
11952  }
11953 
11954  void executeUpdate(Statement statement, String update, int generateKeys) throws SQLException {
11955  ExecuteStatementUpdate executeStatementUpdate = new ExecuteStatementUpdate(statement, update);
11956  executeCommand(executeStatementUpdate);
11957  }
11958 
11959  void executeUpdate(PreparedStatement statement) throws SQLException {
11960  ExecutePreparedStatementUpdate executePreparedStatementUpdate = new ExecutePreparedStatementUpdate(statement);
11961  executeCommand(executePreparedStatementUpdate);
11962  }
11963 
11967  @Override
11968  public void close() {
11969  try {
11970  connection.close();
11971  } catch (SQLException ex) {
11972  logger.log(Level.SEVERE, "Unable to close connection to case database", ex);
11973  }
11974  }
11975 
11976  Connection getConnection() {
11977  return this.connection;
11978  }
11979  }
11980 
11984  private final class SQLiteConnection extends CaseDbConnection {
11985 
11986  private static final int DATABASE_LOCKED_ERROR = 0; // This should be 6 according to documentation, but it has been observed to be 0.
11987  private static final int SQLITE_BUSY_ERROR = 5;
11988 
11989  SQLiteConnection(Connection conn) {
11990  super(conn);
11991  }
11992 
11993  @Override
11994  void executeCommand(DbCommand command) throws SQLException {
11995  int retryCounter = 0;
11996  while (true) {
11997  try {
11998  command.execute(); // Perform the operation
11999  break;
12000  } catch (SQLException ex) {
12001  if ((ex.getErrorCode() == SQLITE_BUSY_ERROR || ex.getErrorCode() == DATABASE_LOCKED_ERROR) && retryCounter < MAX_RETRIES) {
12002  try {
12003 
12004  // We do not notify of error here, as this is not an
12005  // error condition. It is likely a temporary busy or
12006  // locked issue and we will retry.
12007  retryCounter++;
12008  Thread.sleep(SLEEP_LENGTH_IN_MILLISECONDS);
12009  } catch (InterruptedException exp) {
12010  Logger.getLogger(SleuthkitCase.class.getName()).log(Level.WARNING, "Unexpectedly unable to wait for database.", exp);
12011  }
12012  } else {
12013  throw ex;
12014  }
12015  }
12016  }
12017  }
12018  }
12019 
12023  private final class PostgreSQLConnection extends CaseDbConnection {
12024 
12025  private final String COMMUNICATION_ERROR = PSQLState.COMMUNICATION_ERROR.getState();
12026  private final String SYSTEM_ERROR = PSQLState.SYSTEM_ERROR.getState();
12027  private final String UNKNOWN_STATE = PSQLState.UNKNOWN_STATE.getState();
12028  private static final int MAX_RETRIES = 3;
12029 
12030  PostgreSQLConnection(Connection conn) {
12031  super(conn);
12032  }
12033 
12034  @Override
12035  void executeUpdate(Statement statement, String update, int generateKeys) throws SQLException {
12036  CaseDbConnection.ExecuteStatementUpdateGenerateKeys executeStatementUpdateGenerateKeys = new CaseDbConnection.ExecuteStatementUpdateGenerateKeys(statement, update, generateKeys);
12037  executeCommand(executeStatementUpdateGenerateKeys);
12038  }
12039 
12040  @Override
12041  PreparedStatement prepareStatement(String sqlStatement, int generateKeys) throws SQLException {
12042  CaseDbConnection.PrepareStatementGenerateKeys prepareStatementGenerateKeys = new CaseDbConnection.PrepareStatementGenerateKeys(this.getConnection(), sqlStatement, generateKeys);
12043  executeCommand(prepareStatementGenerateKeys);
12044  return prepareStatementGenerateKeys.getPreparedStatement();
12045  }
12046 
12047  @Override
12048  void executeCommand(DbCommand command) throws SQLException {
12049  SQLException lastException = null;
12050  for (int retries = 0; retries < MAX_RETRIES; retries++) {
12051  try {
12052  command.execute();
12053  lastException = null; // reset since we had a successful execution
12054  break;
12055  } catch (SQLException ex) {
12056  lastException = ex;
12057  String sqlState = ex.getSQLState();
12058  if (sqlState == null || sqlState.equals(COMMUNICATION_ERROR) || sqlState.equals(SYSTEM_ERROR) || sqlState.equals(UNKNOWN_STATE)) {
12059  try {
12060  Thread.sleep(SLEEP_LENGTH_IN_MILLISECONDS);
12061  } catch (InterruptedException exp) {
12062  Logger.getLogger(SleuthkitCase.class.getName()).log(Level.WARNING, "Unexpectedly unable to wait for database.", exp);
12063  }
12064  } else {
12065  throw ex;
12066  }
12067  }
12068  }
12069 
12070  // rethrow the exception if we bailed because of too many retries
12071  if (lastException != null) {
12072  throw lastException;
12073  }
12074  }
12075  }
12076 
12091  public static final class CaseDbTransaction {
12092 
12093  private final CaseDbConnection connection;
12094  private SleuthkitCase sleuthkitCase;
12095 
12096  private CaseDbTransaction(SleuthkitCase sleuthkitCase, CaseDbConnection connection) throws TskCoreException {
12097  this.connection = connection;
12098  this.sleuthkitCase = sleuthkitCase;
12099  try {
12100  this.connection.beginTransaction();
12101  } catch (SQLException ex) {
12102  throw new TskCoreException("Failed to create transaction on case database", ex);
12103  }
12104  sleuthkitCase.acquireSingleUserCaseWriteLock();
12105  }
12106 
12114  CaseDbConnection getConnection() {
12115  return this.connection;
12116  }
12117 
12124  public void commit() throws TskCoreException {
12125  try {
12126  this.connection.commitTransaction();
12127  } catch (SQLException ex) {
12128  throw new TskCoreException("Failed to commit transaction on case database", ex);
12129  } finally {
12130  close();
12131  }
12132  }
12133 
12140  public void rollback() throws TskCoreException {
12141  try {
12142  this.connection.rollbackTransactionWithThrow();
12143  } catch (SQLException ex) {
12144  throw new TskCoreException("Case database transaction rollback failed", ex);
12145  } finally {
12146  close();
12147  }
12148  }
12149 
12154  void close() {
12155  this.connection.close();
12156  sleuthkitCase.releaseSingleUserCaseWriteLock();
12157  }
12158  }
12159 
12169  public final class CaseDbQuery implements AutoCloseable {
12170 
12171  private ResultSet resultSet;
12172  private CaseDbConnection connection;
12173 
12174  private CaseDbQuery(String query) throws TskCoreException {
12175  this(query, false);
12176  }
12177 
12178  private CaseDbQuery(String query, boolean allowWriteQuery) throws TskCoreException {
12179  if (!allowWriteQuery) {
12180  if (!query.regionMatches(true, 0, "SELECT", 0, "SELECT".length())) {
12181  throw new TskCoreException("Unsupported query: Only SELECT queries are supported.");
12182  }
12183  }
12184  try {
12185  connection = connections.getConnection();
12186  } catch (TskCoreException ex) {
12187  throw new TskCoreException("Error getting connection for query: ", ex);
12188  }
12189 
12190  try {
12192  resultSet = connection.executeQuery(connection.createStatement(), query);
12193  } catch (SQLException ex) {
12195  throw new TskCoreException("Error executing query: ", ex);
12196  }
12197  }
12198 
12204  public ResultSet getResultSet() {
12205  return resultSet;
12206  }
12207 
12208  @Override
12209  public void close() throws TskCoreException {
12210  try {
12211  if (resultSet != null) {
12212  final Statement statement = resultSet.getStatement();
12213  if (statement != null) {
12214  statement.close();
12215  }
12216  resultSet.close();
12217  }
12218  connection.close();
12219  } catch (SQLException ex) {
12220  throw new TskCoreException("Error closing query: ", ex);
12221  } finally {
12223  }
12224  }
12225  }
12226 
12234  @Deprecated
12235  public void addErrorObserver(ErrorObserver observer) {
12236  sleuthkitCaseErrorObservers.add(observer);
12237  }
12238 
12246  @Deprecated
12247  public void removeErrorObserver(ErrorObserver observer) {
12248  int i = sleuthkitCaseErrorObservers.indexOf(observer);
12249  if (i >= 0) {
12250  sleuthkitCaseErrorObservers.remove(i);
12251  }
12252  }
12253 
12262  @Deprecated
12263  public void submitError(String context, String errorMessage) {
12264  for (ErrorObserver observer : sleuthkitCaseErrorObservers) {
12265  if (observer != null) {
12266  try {
12267  observer.receiveError(context, errorMessage);
12268  } catch (Exception ex) {
12269  logger.log(Level.SEVERE, "Observer client unable to receive message: {0}, {1}", new Object[]{context, errorMessage, ex});
12270 
12271  }
12272  }
12273  }
12274  }
12275 
12281  @Deprecated
12282  public interface ErrorObserver {
12283 
12290  public enum Context {
12291 
12295  IMAGE_READ_ERROR("Image File Read Error"),
12299  DATABASE_READ_ERROR("Database Read Error");
12300 
12301  private final String contextString;
12302 
12303  private Context(String context) {
12304  this.contextString = context;
12305  }
12306 
12307  public String getContextString() {
12308  return contextString;
12309  }
12310  };
12311 
12312  void receiveError(String context, String errorMessage);
12313  }
12314 
12325  @Deprecated
12326  long getDataSourceObjectId(long objectId) {
12327  try {
12328  CaseDbConnection connection = connections.getConnection();
12329  try {
12330  return getDataSourceObjectId(connection, objectId);
12331  } finally {
12332  connection.close();
12333  }
12334  } catch (TskCoreException ex) {
12335  logger.log(Level.SEVERE, "Error getting data source object id for a file", ex);
12336  return 0;
12337  }
12338  }
12339 
12349  @Deprecated
12350  public long getLastObjectId() throws TskCoreException {
12351  CaseDbConnection connection = connections.getConnection();
12353  ResultSet rs = null;
12354  try {
12355  // SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects
12356  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_MAX_OBJECT_ID);
12357  rs = connection.executeQuery(statement);
12358  long id = -1;
12359  if (rs.next()) {
12360  id = rs.getLong("max_obj_id");
12361  }
12362  return id;
12363  } catch (SQLException e) {
12364  throw new TskCoreException("Error getting last object id", e);
12365  } finally {
12366  closeResultSet(rs);
12367  connection.close();
12369  }
12370  }
12371 
12385  @Deprecated
12386  public List<FsContent> findFilesWhere(String sqlWhereClause) throws TskCoreException {
12387  CaseDbConnection connection = connections.getConnection();
12389  Statement s = null;
12390  ResultSet rs = null;
12391  try {
12392  s = connection.createStatement();
12393  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
12394  List<FsContent> results = new ArrayList<FsContent>();
12395  List<AbstractFile> temp = resultSetToAbstractFiles(rs, connection);
12396  for (AbstractFile f : temp) {
12397  final TSK_DB_FILES_TYPE_ENUM type = f.getType();
12398  if (type.equals(TskData.TSK_DB_FILES_TYPE_ENUM.FS)) {
12399  results.add((FsContent) f);
12400  }
12401  }
12402  return results;
12403  } catch (SQLException e) {
12404  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findFilesWhere().", e);
12405  } finally {
12406  closeResultSet(rs);
12407  closeStatement(s);
12408  connection.close();
12410  }
12411  }
12412 
12424  @Deprecated
12425  public int getArtifactTypeID(String artifactTypeName) throws TskCoreException {
12426  CaseDbConnection connection = connections.getConnection();
12428  Statement s = null;
12429  ResultSet rs = null;
12430  try {
12431  s = connection.createStatement();
12432  rs = connection.executeQuery(s, "SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = '" + artifactTypeName + "'"); //NON-NLS
12433  int typeId = -1;
12434  if (rs.next()) {
12435  typeId = rs.getInt("artifact_type_id");
12436  }
12437  return typeId;
12438  } catch (SQLException ex) {
12439  throw new TskCoreException("Error getting artifact type id", ex);
12440  } finally {
12441  closeResultSet(rs);
12442  closeStatement(s);
12443  connection.close();
12445  }
12446  }
12447 
12457  @Deprecated
12458  public ArrayList<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardArtifactTypes() throws TskCoreException {
12459  return new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>(Arrays.asList(BlackboardArtifact.ARTIFACT_TYPE.values()));
12460  }
12461 
12475  @Deprecated
12476  public int addArtifactType(String artifactTypeName, String displayName) throws TskCoreException {
12477  try {
12478  return addBlackboardArtifactType(artifactTypeName, displayName).getTypeID();
12479  } catch (TskDataException ex) {
12480  throw new TskCoreException("Failed to add artifact type.", ex);
12481  }
12482  }
12483 
12497  @Deprecated
12498  public int addAttrType(String attrTypeString, String displayName) throws TskCoreException {
12499  try {
12500  return addArtifactAttributeType(attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, displayName).getTypeID();
12501  } catch (TskDataException ex) {
12502  throw new TskCoreException("Couldn't add new attribute type");
12503  }
12504  }
12505 
12516  @Deprecated
12517  public int getAttrTypeID(String attrTypeName) throws TskCoreException {
12518  CaseDbConnection connection = connections.getConnection();
12520  Statement s = null;
12521  ResultSet rs = null;
12522  try {
12523  s = connection.createStatement();
12524  rs = connection.executeQuery(s, "SELECT attribute_type_id FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName + "'"); //NON-NLS
12525  int typeId = -1;
12526  if (rs.next()) {
12527  typeId = rs.getInt("attribute_type_id");
12528  }
12529  return typeId;
12530  } catch (SQLException ex) {
12531  throw new TskCoreException("Error getting attribute type id", ex);
12532  } finally {
12533  closeResultSet(rs);
12534  closeStatement(s);
12535  connection.close();
12537  }
12538  }
12539 
12552  @Deprecated
12553  public String getAttrTypeString(int attrTypeID) throws TskCoreException {
12554  CaseDbConnection connection = connections.getConnection();
12556  Statement s = null;
12557  ResultSet rs = null;
12558  try {
12559  s = connection.createStatement();
12560  rs = connection.executeQuery(s, "SELECT type_name FROM blackboard_attribute_types WHERE attribute_type_id = " + attrTypeID); //NON-NLS
12561  if (rs.next()) {
12562  return rs.getString("type_name");
12563  } else {
12564  throw new TskCoreException("No type with that id");
12565  }
12566  } catch (SQLException ex) {
12567  throw new TskCoreException("Error getting or creating a attribute type name", ex);
12568  } finally {
12569  closeResultSet(rs);
12570  closeStatement(s);
12571  connection.close();
12573  }
12574  }
12575 
12588  @Deprecated
12589  public String getAttrTypeDisplayName(int attrTypeID) throws TskCoreException {
12590  CaseDbConnection connection = connections.getConnection();
12592  Statement s = null;
12593  ResultSet rs = null;
12594  try {
12595  s = connection.createStatement();
12596  rs = connection.executeQuery(s, "SELECT display_name FROM blackboard_attribute_types WHERE attribute_type_id = " + attrTypeID); //NON-NLS
12597  if (rs.next()) {
12598  return rs.getString("display_name");
12599  } else {
12600  throw new TskCoreException("No type with that id");
12601  }
12602  } catch (SQLException ex) {
12603  throw new TskCoreException("Error getting or creating a attribute type name", ex);
12604  } finally {
12605  closeResultSet(rs);
12606  closeStatement(s);
12607  connection.close();
12609  }
12610  }
12611 
12621  @Deprecated
12622  public ArrayList<BlackboardAttribute.ATTRIBUTE_TYPE> getBlackboardAttributeTypes() throws TskCoreException {
12623  return new ArrayList<BlackboardAttribute.ATTRIBUTE_TYPE>(Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.values()));
12624  }
12625 
12641  @Deprecated
12642  public ResultSet runQuery(String query) throws SQLException {
12643  CaseDbConnection connection;
12644  try {
12645  connection = connections.getConnection();
12646  } catch (TskCoreException ex) {
12647  throw new SQLException("Error getting connection for ad hoc query", ex);
12648  }
12650  try {
12651  return connection.executeQuery(connection.createStatement(), query);
12652  } finally {
12653  //TODO unlock should be done in closeRunQuery()
12654  //but currently not all code calls closeRunQuery - need to fix this
12655  connection.close();
12657  }
12658  }
12659 
12669  @Deprecated
12670  public void closeRunQuery(ResultSet resultSet) throws SQLException {
12671  final Statement statement = resultSet.getStatement();
12672  resultSet.close();
12673  if (statement != null) {
12674  statement.close();
12675  }
12676  }
12677 
12694  @Deprecated
12695  public LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, long containerId, List<TskFileRange> data) throws TskCoreException {
12696  CarvingResult.CarvedFile carvedFile = new CarvingResult.CarvedFile(carvedFileName, carvedFileSize, data);
12697  List<CarvingResult.CarvedFile> files = new ArrayList<CarvingResult.CarvedFile>();
12698  files.add(carvedFile);
12699  CarvingResult carvingResult;
12700  Content parent = getContentById(containerId);
12701  if (parent instanceof FileSystem
12702  || parent instanceof Volume
12703  || parent instanceof Image) {
12704  carvingResult = new CarvingResult(parent, files);
12705  } else {
12706  throw new TskCoreException(String.format("Parent (id =%d) is not an file system, volume or image", containerId));
12707  }
12708  return addCarvedFiles(carvingResult).get(0);
12709  }
12710 
12724  @Deprecated
12725  public List<LayoutFile> addCarvedFiles(List<CarvedFileContainer> filesToAdd) throws TskCoreException {
12726  List<CarvingResult.CarvedFile> carvedFiles = new ArrayList<CarvingResult.CarvedFile>();
12727  for (CarvedFileContainer container : filesToAdd) {
12728  CarvingResult.CarvedFile carvedFile = new CarvingResult.CarvedFile(container.getName(), container.getSize(), container.getRanges());
12729  carvedFiles.add(carvedFile);
12730  }
12731  CarvingResult carvingResult;
12732  Content parent = getContentById(filesToAdd.get(0).getId());
12733  if (parent instanceof FileSystem
12734  || parent instanceof Volume
12735  || parent instanceof Image) {
12736  carvingResult = new CarvingResult(parent, carvedFiles);
12737  } else {
12738  throw new TskCoreException(String.format("Parent (id =%d) is not an file system, volume or image", parent.getId()));
12739  }
12740  return addCarvedFiles(carvingResult);
12741  }
12742 
12772  @Deprecated
12773  public DerivedFile addDerivedFile(String fileName, String localPath,
12774  long size, long ctime, long crtime, long atime, long mtime,
12775  boolean isFile, AbstractFile parentFile,
12776  String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException {
12777  return addDerivedFile(fileName, localPath, size, ctime, crtime, atime, mtime,
12778  isFile, parentFile, rederiveDetails, toolName, toolVersion,
12779  otherDetails, TskData.EncodingType.NONE);
12780  }
12781 
12806  @Deprecated
12807  public LocalFile addLocalFile(String fileName, String localPath,
12808  long size, long ctime, long crtime, long atime, long mtime,
12809  boolean isFile,
12810  AbstractFile parent, CaseDbTransaction transaction) throws TskCoreException {
12811  return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile,
12812  TskData.EncodingType.NONE, parent, transaction);
12813  }
12814 
12834  @Deprecated
12835  public LocalFile addLocalFile(String fileName, String localPath,
12836  long size, long ctime, long crtime, long atime, long mtime,
12837  boolean isFile,
12838  AbstractFile parent) throws TskCoreException {
12839  return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime,
12840  isFile, TskData.EncodingType.NONE, parent);
12841  }
12842 
12859  @Deprecated
12860  public AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans) {
12861  return this.caseHandle.initAddImageProcess(timezone, addUnallocSpace, noFatFsOrphans, "", this);
12862  }
12863 
12874  @Deprecated
12875  public Collection<FileSystem> getFileSystems(Image image) {
12876  try {
12877  return getImageFileSystems(image);
12878  } catch (TskCoreException ex) {
12879  logger.log(Level.SEVERE, "Error loading all file systems for image with ID {0}", image.getId());
12880  return new ArrayList<>();
12881  }
12882  }
12883 
12891  @Deprecated
12892  public void acquireExclusiveLock() {
12894  }
12895 
12903  @Deprecated
12904  public void releaseExclusiveLock() {
12906  }
12907 
12915  @Deprecated
12916  public void acquireSharedLock() {
12918  }
12919 
12927  @Deprecated
12928  public void releaseSharedLock() {
12930  }
12931 };
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, long value)
final IngestJobInfo addIngestJob(Content dataSource, String hostName, List< IngestModuleInfo > ingestModules, Date jobStart, Date jobEnd, IngestJobStatusType status, String settingsDir)
FS
File that can be found in file system tree.
Definition: TskData.java:676
static FileKnown valueOf(byte known)
Definition: TskData.java:801
BlackboardArtifact getArtifactByArtifactId(long id)
AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans)
BlackboardArtifact getArtifactById(long id)
ArrayList< BlackboardAttribute > getBlackboardAttributes(final BlackboardArtifact artifact)
int getArtifactTypeID(String artifactTypeName)
long getBlackboardArtifactTagsCountByTagName(TagName tagName)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(ARTIFACT_TYPE artifactType)
LocalDirectory addLocalDirectory(long parentId, String directoryName, CaseDbTransaction transaction)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(String artifactTypeName)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, int value)
void addBlackboardAttributes(Collection< BlackboardAttribute > attributes, int artifactTypeId)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(int artifactTypeID, long obj_id)
CommunicationsManager getCommunicationsManager()
DerivedFile addDerivedFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, AbstractFile parentFile, String rederiveDetails, String toolName, String toolVersion, String otherDetails)
boolean isCompatible(CaseDbSchemaVersionNumber dbSchemaVersion)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, AbstractFile parent)
ALLOC
Metadata structure is currently in an allocated state.
Definition: TskData.java:206
static TSK_FS_TYPE_ENUM valueOf(int fsTypeValue)
Definition: TskData.java:501
CaseDbSchemaVersionNumber getDBSchemaCreationVersion()
ArrayList< BlackboardArtifact > getBlackboardArtifacts(int artifactTypeID)
void addErrorObserver(ErrorObserver observer)
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)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, String md5, FileKnown known, String mimeType, boolean isFile, TskData.EncodingType encodingType, Content parent, CaseDbTransaction transaction)
List< AbstractFile > findFiles(Content dataSource, String fileName, AbstractFile parentFile)
TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus)
void setFileMIMEType(AbstractFile file, String mimeType)
UNALLOC
Metadata structure is currently in an unallocated state.
Definition: TskData.java:207
void addBlackboardAttribute(BlackboardAttribute attr, int artifactTypeId)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, AbstractFile parent, CaseDbTransaction transaction)
final List< LayoutFile > addLayoutFiles(Content parent, List< TskFileRange > fileRanges)
int addArtifactType(String artifactTypeName, String displayName)
BlackboardArtifactTagChange addArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment)
synchronized CaseDbAccessManager getCaseDbAccessManager()
BlackboardArtifactTag getBlackboardArtifactTagByID(long artifactTagID)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, double value)
List< AbstractFile > openFiles(Content dataSource, String filePath)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)
final IngestModuleInfo addIngestModule(String displayName, String factoryClassName, IngestModuleType type, String version)
long getBlackboardArtifactsCount(String artifactTypeName, long obj_id)
static IngestJobStatusType fromID(int typeId)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, byte value)
LAYOUT_FILE
Set of blocks from an image that have been designated as a file.
Definition: TskData.java:685
static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir)
List< VirtualDirectory > getVirtualDirectoryRoots()
LayoutFile addLayoutFile(String fileName, long size, TSK_FS_NAME_FLAG_ENUM dirFlag, TSK_FS_META_FLAG_ENUM metaFlag, long ctime, long crtime, long atime, long mtime, List< TskFileRange > fileRanges, Content parent)
long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId)
ArrayList< BlackboardArtifact.ARTIFACT_TYPE > getBlackboardArtifactTypes()
ContentTag getContentTagByID(long contentTagID)
LOCAL
Local file that was added (not from a disk image)
Definition: TskData.java:679
Map< Long, List< String > > getImagePaths()
List< Long > findAllFileIdsWhere(String sqlWhereClause)
synchronized TaggingManager getTaggingManager()
BlackboardArtifact getBlackboardArtifact(long artifactID)
List< BlackboardArtifact.Type > getArtifactTypesInUse()
BlackboardAttribute.Type addArtifactAttributeType(String attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
CARVED
Set of blocks for a file found from carving. Could be on top of a TSK_DB_FILES_TYPE_UNALLOC_BLOCKS ra...
Definition: TskData.java:677
BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment)
long countFilesWhere(String sqlWhereClause)
long getBlackboardArtifactsCount(ARTIFACT_TYPE artifactType, long obj_id)
FS
File System - see tsk_fs_info for more details.
Definition: TskData.java:631
Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTransaction transaction)
boolean isFileFromSource(Content dataSource, long fileId)
ArrayList< BlackboardArtifact > getMatchingArtifacts(String whereClause)
VirtualDirectory addVirtualDirectory(long parentId, String directoryName, CaseDbTransaction transaction)
ArrayList< BlackboardArtifact.ARTIFACT_TYPE > getBlackboardArtifactTypesInUse()
int getAttrTypeID(String attrTypeName)
Report addReport(String localPath, String sourceModuleName, String reportName, Content parent)
List< Content > getChildren()
USED
Metadata structure has been allocated at least once.
Definition: TskData.java:208
void unregisterForEvents(Object listener)
LOCAL_DIR
Local directory that was added (not from a disk image)
Definition: TskData.java:684
final List< LayoutFile > addCarvedFiles(CarvingResult carvingResult)
VOL
Volume - see tsk_vs_parts for more details.
Definition: TskData.java:630
void closeRunQuery(ResultSet resultSet)
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)
int addAttrType(String attrTypeString, String displayName)
void deleteBlackboardArtifactTag(BlackboardArtifactTag tag)
long getContentTagsCountByTagName(TagName tagName, long dsObjId)
List< ContentTag > getContentTagsByTagName(TagName tagName)
BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id)
static String escapeSingleQuotes(String text)
String getAttrTypeDisplayName(int attrTypeID)
List< BlackboardArtifact > getBlackboardArtifacts(ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value)
List< AbstractFile > findFiles(Content dataSource, String fileName)
BlackboardAttribute.Type getAttributeType(String attrTypeName)
Image addImageInfo(long deviceObjId, List< String > imageFilePaths, String timeZone)
static HTML_COLOR getColorByName(String colorName)
Definition: TagName.java:76
REPORT
Artifact - see blackboard_artifacts for more details.
Definition: TskData.java:634
List< AbstractFile > findFilesByMd5(String md5Hash)
long getBlackboardArtifactsTypeCount(int artifactTypeID, long dataSourceID)
BlackboardArtifact.Type getArtifactType(String artTypeName)
BlackboardArtifact newBlackboardArtifact(ARTIFACT_TYPE artifactType, long obj_id)
DERIVED
File derived from a parent file (i.e. from ZIP)
Definition: TskData.java:678
List< LayoutFile > addCarvedFiles(List< CarvedFileContainer > filesToAdd)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByTagName(TagName tagName)
static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath)
Report addReport(String localPath, String sourceModuleName, String reportName)
List< BlackboardArtifactTag > getAllBlackboardArtifactTags()
ArrayList< BlackboardArtifact > getBlackboardArtifacts(String artifactTypeName, long obj_id)
Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List< String > imagePaths, String timezone, String md5, String sha1, String sha256, String deviceId, CaseDbTransaction transaction)
void removeErrorObserver(ErrorObserver observer)
List< AbstractFile > findFiles(Content dataSource, String fileName, String dirSubString)
ContentTagChange addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset)
FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS_TYPE_ENUM type, long blockSize, long blockCount, long rootInum, long firstInum, long lastInum, String displayName, CaseDbTransaction transaction)
LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, long containerId, List< TskFileRange > data)
ArrayList< BlackboardAttribute.ATTRIBUTE_TYPE > getBlackboardAttributeTypes()
UNALLOC_BLOCKS
Set of blocks not allocated by file system. Parent should be image, volume, or file system...
Definition: TskData.java:680
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, TskData.EncodingType encodingType, AbstractFile parent)
ArrayList< BlackboardAttribute > getMatchingAttributes(String whereClause)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value)
long getBlackboardArtifactsTypeCount(int artifactTypeID)
List< ContentTag > getContentTagsByTagName(TagName tagName, long dsObjId)
static ObjectType valueOf(short objectType)
Definition: TskData.java:659
long getContentTagsCountByTagName(TagName tagName)
FsContent addFileSystemFile(long dataSourceObjId, long fsObjId, String fileName, long metaAddr, int metaSeq, TSK_FS_ATTR_TYPE_ENUM attrType, int attrId, TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, Content parent)
Collection< FileSystem > getImageFileSystems(Image image)
void updateImagePath(String newPath, long objectId)
VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset, long blockSize, CaseDbTransaction transaction)
UNKNOWN
File marked as unknown by hash db.
Definition: TskData.java:782
List< TagName > getTagNamesInUse(long dsObjId)
List< AbstractFile > findAllFilesWhere(String sqlWhereClause)
boolean setKnown(AbstractFile file, FileKnown fileKnown)
static void tryConnect(CaseDbConnectionInfo info)
static SleuthkitCase openCase(String dbPath)
CaseDbQuery executeInsertOrUpdate(String query)
static String createNonUniquePath(String uniquePath)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId)
Volume addVolume(long parentObjId, long addr, long start, long length, String desc, long flags, CaseDbTransaction transaction)
long getBlackboardArtifactsCount(int artifactTypeID, long obj_id)
void submitError(String context, String errorMessage)
final List< IngestJobInfo > getIngestJobs()
VIRTUAL_DIR
Virtual directory (not on fs) with no meta-data entry that can be used to group files of types other ...
Definition: TskData.java:682
static SleuthkitCase newCase(String dbPath)
VirtualDirectory addVirtualDirectory(long parentId, String directoryName)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, TskData.EncodingType encodingType, Content parent, CaseDbTransaction transaction)
List< ContentTag > getContentTagsByContent(Content content)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(ARTIFACT_TYPE artifactType, long obj_id)
int countFsContentType(TskData.TSK_FS_META_TYPE_ENUM contentType)
TagName addTagName(String displayName, String description, TagName.HTML_COLOR color)
ABSTRACTFILE
File - see tsk_files for more details.
Definition: TskData.java:632
ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset)
DataSource getDataSource(long objectId)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String subString, boolean startsWith)
Iterable< BlackboardArtifact.Type > getArtifactTypes()
List< BlackboardAttribute.Type > getAttributeTypes()
LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, CaseDbTransaction transaction)
AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath)
List< FsContent > findFilesWhere(String sqlWhereClause)
List< TskFileRange > getFileRanges(long id)
BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName)
CaseDbQuery executeQuery(String query)
void setReviewStatus(BlackboardArtifact artifact, BlackboardArtifact.ReviewStatus newStatus)
void setImagePaths(long obj_id, List< String > paths)
VS
Volume System - see tsk_vs_info for more details.
Definition: TskData.java:629
IMG
Disk Image - see tsk_image_info for more details.
Definition: TskData.java:628
UNALLOC
Name is in an unallocated state.
Definition: TskData.java:157
Collection< FileSystem > getFileSystems(Image image)
LocalDirectory addLocalDirectory(long parentId, String directoryName)

Copyright © 2011-2020 Brian Carrier. (carrier -at- sleuthkit -dot- org)
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.