Sleuth Kit Java Bindings (JNI)  4.10.1
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-2020 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.Properties;
61 import java.util.ResourceBundle;
62 import java.util.Set;
63 import java.util.UUID;
64 import java.util.concurrent.ConcurrentHashMap;
65 import java.util.concurrent.locks.ReentrantReadWriteLock;
66 import java.util.logging.Level;
67 import java.util.logging.Logger;
68 import org.postgresql.util.PSQLState;
84 import org.sqlite.SQLiteConfig;
85 import org.sqlite.SQLiteDataSource;
86 import org.sqlite.SQLiteJDBCLoader;
87 
92 public class SleuthkitCase {
93 
94  private static final int MAX_DB_NAME_LEN_BEFORE_TIMESTAMP = 47;
95 
100  static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
101  = new CaseDbSchemaVersionNumber(8, 6);
102 
103  private static final long BASE_ARTIFACT_ID = Long.MIN_VALUE; // Artifact ids will start at the lowest negative value
104  private static final Logger logger = Logger.getLogger(SleuthkitCase.class.getName());
105  private static final ResourceBundle bundle = ResourceBundle.getBundle("org.sleuthkit.datamodel.Bundle");
106  private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
107  private static final String SQL_ERROR_CONNECTION_GROUP = "08";
108  private static final String SQL_ERROR_AUTHENTICATION_GROUP = "28";
109  private static final String SQL_ERROR_PRIVILEGE_GROUP = "42";
110  private static final String SQL_ERROR_RESOURCE_GROUP = "53";
111  private static final String SQL_ERROR_LIMIT_GROUP = "54";
112  private static final String SQL_ERROR_INTERNAL_GROUP = "xx";
113  private static final int MIN_USER_DEFINED_TYPE_ID = 10000;
114 
115  private static final Set<String> CORE_TABLE_NAMES = ImmutableSet.of(
116  "tsk_events",
117  "tsk_event_descriptions",
118  "tsk_event_types",
119  "tsk_db_info",
120  "tsk_objects",
121  "tsk_image_info",
122  "tsk_image_names",
123  "tsk_vs_info",
124  "tsk_vs_parts",
125  "tsk_fs_info",
126  "tsk_file_layout",
127  "tsk_files",
128  "tsk_files_path",
129  "tsk_files_derived",
130  "tsk_files_derived_method",
131  "tag_names",
132  "content_tags",
133  "blackboard_artifact_tags",
134  "blackboard_artifacts",
135  "blackboard_attributes",
136  "blackboard_artifact_types",
137  "blackboard_attribute_types",
138  "data_source_info",
139  "file_encoding_types",
140  "ingest_module_types",
141  "ingest_job_status_types",
142  "ingest_modules",
143  "ingest_jobs",
144  "ingest_job_modules",
145  "account_types",
146  "accounts",
147  "account_relationships",
148  "review_statuses",
149  "reports,");
150 
151  private static final Set<String> CORE_INDEX_NAMES = ImmutableSet.of(
152  "parObjId",
153  "layout_objID",
154  "artifact_objID",
155  "artifact_artifact_objID",
156  "artifact_typeID",
157  "attrsArtifactID",
158  "mime_type",
159  "file_extension",
160  "relationships_account1",
161  "relationships_account2",
162  "relationships_relationship_source_obj_id",
163  "relationships_date_time",
164  "relationships_relationship_type",
165  "relationships_data_source_obj_id",
166  "events_time",
167  "events_type",
168  "events_data_source_obj_id",
169  "events_file_obj_id",
170  "events_artifact_id");
171 
172  private static final String TSK_VERSION_KEY = "TSK_VER";
173  private static final String SCHEMA_MAJOR_VERSION_KEY = "SCHEMA_MAJOR_VERSION";
174  private static final String SCHEMA_MINOR_VERSION_KEY = "SCHEMA_MINOR_VERSION";
175  private static final String CREATION_SCHEMA_MAJOR_VERSION_KEY = "CREATION_SCHEMA_MAJOR_VERSION";
176  private static final String CREATION_SCHEMA_MINOR_VERSION_KEY = "CREATION_SCHEMA_MINOR_VERSION";
177 
178  private final ConnectionPool connections;
179  private final Map<Long, VirtualDirectory> rootIdsToCarvedFileDirs = new HashMap<>();
180  private final Map<Long, FileSystem> fileSystemIdMap = new HashMap<>(); // Cache for file system files.
181  private final List<ErrorObserver> sleuthkitCaseErrorObservers = new ArrayList<>();
182  private final String databaseName;
183  private final String dbPath;
184  private final DbType dbType;
185  private final String caseDirPath;
186  private SleuthkitJNI.CaseDbHandle caseHandle;
187  private final String caseHandleIdentifier; // Used to identify this case in the JNI cache.
188  private String dbBackupPath;
189  private Map<Integer, BlackboardArtifact.Type> typeIdToArtifactTypeMap;
190  private Map<Integer, BlackboardAttribute.Type> typeIdToAttributeTypeMap;
191  private Map<String, BlackboardArtifact.Type> typeNameToArtifactTypeMap;
192  private Map<String, BlackboardAttribute.Type> typeNameToAttributeTypeMap;
193  private CaseDbSchemaVersionNumber caseDBSchemaCreationVersion;
194 
195  /*
196  * First parameter is used to specify the SparseBitSet to use, as object IDs
197  * can be larger than the max size of a SparseBitSet
198  */
199  private final Map<Long, SparseBitSet> hasChildrenBitSetMap = new HashMap<>();
200 
201  private long nextArtifactId; // Used to ensure artifact ids come from the desired range.
202  // This read/write lock is used to implement a layer of locking on top of
203  // the locking protocol provided by the underlying SQLite database. The Java
204  // locking protocol improves performance for reasons that are not currently
205  // understood. Note that the lock is contructed to use a fairness policy.
206  private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
207 
208  private CommunicationsManager communicationsMgr;
209  private TimelineManager timelineMgr;
210  private Blackboard blackboard;
211  private CaseDbAccessManager dbAccessManager;
212  private TaggingManager taggingMgr;
213 
214  private final Map<String, Set<Long>> deviceIdToDatasourceObjIdMap = new HashMap<>();
215 
216  private final EventBus eventBus = new EventBus("SleuthkitCase-EventBus");
217 
218  public void registerForEvents(Object listener) {
219  eventBus.register(listener);
220  }
221 
222  public void unregisterForEvents(Object listener) {
223  eventBus.unregister(listener);
224  }
225 
226  void fireTSKEvent(Object event) {
227  eventBus.post(event);
228  }
229 
230  // Cache of frequently used content objects (e.g. data source, file system).
231  private final Map<Long, Content> frequentlyUsedContentMap = new HashMap<>();
232 
233  private Examiner cachedCurrentExaminer = null;
234 
235  static {
236  Properties p = new Properties(System.getProperties());
237  p.put("com.mchange.v2.log.MLog", "com.mchange.v2.log.FallbackMLog");
238  p.put("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "SEVERE");
239  System.setProperties(p);
240  }
241 
256  public static void tryConnect(CaseDbConnectionInfo info) throws TskCoreException {
257  // Check if we can talk to the database.
258  if (info.getHost() == null || info.getHost().isEmpty()) {
259  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingHostname")); //NON-NLS
260  } else if (info.getPort() == null || info.getPort().isEmpty()) {
261  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingPort")); //NON-NLS
262  } else if (info.getUserName() == null || info.getUserName().isEmpty()) {
263  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingUsername")); //NON-NLS
264  } else if (info.getPassword() == null || info.getPassword().isEmpty()) {
265  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingPassword")); //NON-NLS
266  }
267 
268  try {
269  Class.forName("org.postgresql.Driver"); //NON-NLS
270  Connection conn = DriverManager.getConnection("jdbc:postgresql://" + info.getHost() + ":" + info.getPort() + "/postgres", info.getUserName(), info.getPassword()); //NON-NLS
271  if (conn != null) {
272  conn.close();
273  }
274  } catch (SQLException ex) {
275  String result;
276  String sqlState = ex.getSQLState().toLowerCase();
277  if (sqlState.startsWith(SQL_ERROR_CONNECTION_GROUP)) {
278  try {
279  if (InetAddress.getByName(info.getHost()).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
280  // if we can reach the host, then it's probably port problem
281  result = bundle.getString("DatabaseConnectionCheck.Port"); //NON-NLS
282  } else {
283  result = bundle.getString("DatabaseConnectionCheck.HostnameOrPort"); //NON-NLS
284  }
285  } catch (IOException | MissingResourceException any) {
286  // it may be anything
287  result = bundle.getString("DatabaseConnectionCheck.Everything"); //NON-NLS
288  }
289  } else if (sqlState.startsWith(SQL_ERROR_AUTHENTICATION_GROUP)) {
290  result = bundle.getString("DatabaseConnectionCheck.Authentication"); //NON-NLS
291  } else if (sqlState.startsWith(SQL_ERROR_PRIVILEGE_GROUP)) {
292  result = bundle.getString("DatabaseConnectionCheck.Access"); //NON-NLS
293  } else if (sqlState.startsWith(SQL_ERROR_RESOURCE_GROUP)) {
294  result = bundle.getString("DatabaseConnectionCheck.ServerDiskSpace"); //NON-NLS
295  } else if (sqlState.startsWith(SQL_ERROR_LIMIT_GROUP)) {
296  result = bundle.getString("DatabaseConnectionCheck.ServerRestart"); //NON-NLS
297  } else if (sqlState.startsWith(SQL_ERROR_INTERNAL_GROUP)) {
298  result = bundle.getString("DatabaseConnectionCheck.InternalServerIssue"); //NON-NLS
299  } else {
300  result = bundle.getString("DatabaseConnectionCheck.Connection"); //NON-NLS
301  }
302  throw new TskCoreException(result);
303  } catch (ClassNotFoundException ex) {
304  throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.Installation")); //NON-NLS
305  }
306  }
307 
319  private SleuthkitCase(String dbPath, SleuthkitJNI.CaseDbHandle caseHandle, DbType dbType) throws Exception {
320  Class.forName("org.sqlite.JDBC");
321  this.dbPath = dbPath;
322  this.dbType = dbType;
323  File dbFile = new File(dbPath);
324  this.caseDirPath = dbFile.getParentFile().getAbsolutePath();
325  this.databaseName = dbFile.getName();
326  this.connections = new SQLiteConnections(dbPath);
327  this.caseHandle = caseHandle;
328  this.caseHandleIdentifier = caseHandle.getCaseDbIdentifier();
329  init();
330  logSQLiteJDBCDriverInfo();
331  }
332 
350  private SleuthkitCase(String host, int port, String dbName, String userName, String password, SleuthkitJNI.CaseDbHandle caseHandle, String caseDirPath, DbType dbType) throws Exception {
351  this.dbPath = "";
352  this.databaseName = dbName;
353  this.dbType = dbType;
354  this.caseDirPath = caseDirPath;
355  this.connections = new PostgreSQLConnections(host, port, dbName, userName, password);
356  this.caseHandle = caseHandle;
357  this.caseHandleIdentifier = caseHandle.getCaseDbIdentifier();
358  init();
359  }
360 
361  private void init() throws Exception {
362  typeIdToArtifactTypeMap = new ConcurrentHashMap<>();
363  typeIdToAttributeTypeMap = new ConcurrentHashMap<>();
364  typeNameToArtifactTypeMap = new ConcurrentHashMap<>();
365  typeNameToAttributeTypeMap = new ConcurrentHashMap<>();
366 
367  /*
368  * The following methods need to be called before updateDatabaseSchema
369  * due to the way that updateFromSchema2toSchema3 was implemented.
370  */
371  initBlackboardArtifactTypes();
372  initBlackboardAttributeTypes();
373  initNextArtifactId();
374  updateDatabaseSchema(null);
375 
376  try (CaseDbConnection connection = connections.getConnection()) {
377  initIngestModuleTypes(connection);
378  initIngestStatusTypes(connection);
379  initReviewStatuses(connection);
380  initEncodingTypes(connection);
381  populateHasChildrenMap(connection);
382  updateExaminers(connection);
383  initDBSchemaCreationVersion(connection);
384  }
385 
386  blackboard = new Blackboard(this);
387  communicationsMgr = new CommunicationsManager(this);
388  timelineMgr = new TimelineManager(this);
389  dbAccessManager = new CaseDbAccessManager(this);
390  taggingMgr = new TaggingManager(this);
391  }
392 
398  static Set<String> getCoreTableNames() {
399  return CORE_TABLE_NAMES;
400  }
401 
407  static Set<String> getCoreIndexNames() {
408  return CORE_INDEX_NAMES;
409  }
410 
419  boolean getHasChildren(Content content) {
420  long objId = content.getId();
421  long mapIndex = objId / Integer.MAX_VALUE;
422  int mapValue = (int) (objId % Integer.MAX_VALUE);
423 
424  synchronized (hasChildrenBitSetMap) {
425  if (hasChildrenBitSetMap.containsKey(mapIndex)) {
426  return hasChildrenBitSetMap.get(mapIndex).get(mapValue);
427  }
428  return false;
429  }
430  }
431 
437  private void setHasChildren(Long objId) {
438  long mapIndex = objId / Integer.MAX_VALUE;
439  int mapValue = (int) (objId % Integer.MAX_VALUE);
440 
441  synchronized (hasChildrenBitSetMap) {
442  if (hasChildrenBitSetMap.containsKey(mapIndex)) {
443  hasChildrenBitSetMap.get(mapIndex).set(mapValue);
444  } else {
445  SparseBitSet bitSet = new SparseBitSet();
446  bitSet.set(mapValue);
447  hasChildrenBitSetMap.put(mapIndex, bitSet);
448  }
449  }
450  }
451 
460  return communicationsMgr;
461  }
462 
469  return blackboard;
470  }
471 
480  return timelineMgr;
481  }
482 
483  /*
484  * Gets the case database access manager for this case.
485  *
486  * @return The per case CaseDbAccessManager object.
487  *
488  * @throws org.sleuthkit.datamodel.TskCoreException
489  */
491  return dbAccessManager;
492  }
493 
499  public synchronized TaggingManager getTaggingManager() {
500  return taggingMgr;
501  }
502 
509  private void initBlackboardArtifactTypes() throws SQLException, TskCoreException {
510  CaseDbConnection connection = connections.getConnection();
511  Statement statement = null;
512  ResultSet resultSet = null;
514  try {
515  statement = connection.createStatement();
516  for (ARTIFACT_TYPE type : ARTIFACT_TYPE.values()) {
517  try {
518  statement.execute("INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name) VALUES (" + type.getTypeID() + " , '" + type.getLabel() + "', '" + type.getDisplayName() + "')"); //NON-NLS
519  } catch (SQLException ex) {
520  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM blackboard_artifact_types WHERE artifact_type_id = '" + type.getTypeID() + "'"); //NON-NLS
521  resultSet.next();
522  if (resultSet.getLong("count") == 0) {
523  throw ex;
524  }
525  resultSet.close();
526  resultSet = null;
527  }
528  this.typeIdToArtifactTypeMap.put(type.getTypeID(), new BlackboardArtifact.Type(type));
529  this.typeNameToArtifactTypeMap.put(type.getLabel(), new BlackboardArtifact.Type(type));
530  }
531  if (dbType == DbType.POSTGRESQL) {
532  int newPrimaryKeyIndex = Collections.max(Arrays.asList(ARTIFACT_TYPE.values())).getTypeID() + 1;
533  statement.execute("ALTER SEQUENCE blackboard_artifact_types_artifact_type_id_seq RESTART WITH " + newPrimaryKeyIndex); //NON-NLS
534  }
535  } finally {
536  closeResultSet(resultSet);
537  closeStatement(statement);
538  connection.close();
540  }
541  }
542 
550  private void initBlackboardAttributeTypes() throws SQLException, TskCoreException {
551  CaseDbConnection connection = connections.getConnection();
552  Statement statement = null;
553  ResultSet resultSet = null;
555  try {
556  statement = connection.createStatement();
557  for (ATTRIBUTE_TYPE type : ATTRIBUTE_TYPE.values()) {
558  try {
559  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
560  } catch (SQLException ex) {
561  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM blackboard_attribute_types WHERE attribute_type_id = '" + type.getTypeID() + "'"); //NON-NLS
562  resultSet.next();
563  if (resultSet.getLong("count") == 0) {
564  throw ex;
565  }
566  resultSet.close();
567  resultSet = null;
568  }
569  this.typeIdToAttributeTypeMap.put(type.getTypeID(), new BlackboardAttribute.Type(type));
570  this.typeNameToAttributeTypeMap.put(type.getLabel(), new BlackboardAttribute.Type(type));
571  }
572  if (this.dbType == DbType.POSTGRESQL) {
573  int newPrimaryKeyIndex = Collections.max(Arrays.asList(ATTRIBUTE_TYPE.values())).getTypeID() + 1;
574  statement.execute("ALTER SEQUENCE blackboard_attribute_types_attribute_type_id_seq RESTART WITH " + newPrimaryKeyIndex); //NON-NLS
575  }
576  } finally {
577  closeResultSet(resultSet);
578  closeStatement(statement);
579  connection.close();
581  }
582  }
583 
593  private void initNextArtifactId() throws SQLException, TskCoreException {
594  CaseDbConnection connection = connections.getConnection();
595  Statement statement = null;
596  ResultSet resultSet = null;
598  try {
599  statement = connection.createStatement();
600  resultSet = connection.executeQuery(statement, "SELECT MAX(artifact_id) AS max_artifact_id FROM blackboard_artifacts"); //NON-NLS
601  resultSet.next();
602  this.nextArtifactId = resultSet.getLong("max_artifact_id") + 1;
603  if (this.nextArtifactId == 1) {
604  this.nextArtifactId = BASE_ARTIFACT_ID;
605  }
606  } finally {
607  closeResultSet(resultSet);
608  closeStatement(statement);
609  connection.close();
611  }
612  }
613 
621  private void initIngestModuleTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
622  Statement statement = null;
623  ResultSet resultSet = null;
625  try {
626  statement = connection.createStatement();
627  for (IngestModuleType type : IngestModuleType.values()) {
628  try {
629  statement.execute("INSERT INTO ingest_module_types (type_id, type_name) VALUES (" + type.ordinal() + ", '" + type.toString() + "');"); //NON-NLS
630  } catch (SQLException ex) {
631  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM ingest_module_types WHERE type_id = " + type.ordinal() + ";"); //NON-NLS
632  resultSet.next();
633  if (resultSet.getLong("count") == 0) {
634  throw ex;
635  }
636  resultSet.close();
637  resultSet = null;
638  }
639  }
640  } finally {
641  closeResultSet(resultSet);
642  closeStatement(statement);
644  }
645  }
646 
654  private void initIngestStatusTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
655  Statement statement = null;
656  ResultSet resultSet = null;
658  try {
659  statement = connection.createStatement();
660  for (IngestJobStatusType type : IngestJobStatusType.values()) {
661  try {
662  statement.execute("INSERT INTO ingest_job_status_types (type_id, type_name) VALUES (" + type.ordinal() + ", '" + type.toString() + "');"); //NON-NLS
663  } catch (SQLException ex) {
664  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM ingest_job_status_types WHERE type_id = " + type.ordinal() + ";"); //NON-NLS
665  resultSet.next();
666  if (resultSet.getLong("count") == 0) {
667  throw ex;
668  }
669  resultSet.close();
670  resultSet = null;
671  }
672  }
673  } finally {
674  closeResultSet(resultSet);
675  closeStatement(statement);
677  }
678  }
679 
686  private void initReviewStatuses(CaseDbConnection connection) throws SQLException, TskCoreException {
687  Statement statement = null;
688  ResultSet resultSet = null;
690  try {
691  statement = connection.createStatement();
692  for (BlackboardArtifact.ReviewStatus status : BlackboardArtifact.ReviewStatus.values()) {
693  try {
694  statement.execute("INSERT INTO review_statuses (review_status_id, review_status_name, display_name) " //NON-NLS
695  + "VALUES (" + status.getID() + ",'" + status.getName() + "','" + status.getDisplayName() + "')"); //NON-NLS
696  } catch (SQLException ex) {
697  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM review_statuses WHERE review_status_id = " + status.getID()); //NON-NLS
698  resultSet.next();
699  if (resultSet.getLong("count") == 0) {
700  throw ex;
701  }
702  resultSet.close();
703  resultSet = null;
704  }
705  }
706  } finally {
707  closeResultSet(resultSet);
708  closeStatement(statement);
710  }
711  }
712 
720  private void initEncodingTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
721  Statement statement = null;
722  ResultSet resultSet = null;
724  try {
725  statement = connection.createStatement();
726  for (TskData.EncodingType type : TskData.EncodingType.values()) {
727  try {
728  statement.execute("INSERT INTO file_encoding_types (encoding_type, name) VALUES (" + type.getType() + " , '" + type.name() + "')"); //NON-NLS
729  } catch (SQLException ex) {
730  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM file_encoding_types WHERE encoding_type = " + type.getType()); //NON-NLS
731  resultSet.next();
732  if (resultSet.getLong("count") == 0) {
733  throw ex;
734  }
735  resultSet.close();
736  resultSet = null;
737  }
738  }
739  } finally {
740  closeResultSet(resultSet);
741  closeStatement(statement);
743  }
744  }
745 
754  private void updateExaminers(CaseDbConnection connection) throws SQLException, TskCoreException {
755 
756  String loginName = System.getProperty("user.name");
757  if (loginName.isEmpty()) {
758  logger.log(Level.SEVERE, "Cannot determine logged in user name");
759  return;
760  }
761 
763  try {
764  PreparedStatement statement;
765  switch (getDatabaseType()) {
766  case POSTGRESQL:
767  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_EXAMINER_POSTGRESQL);
768  break;
769  case SQLITE:
770  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_EXAMINER_SQLITE);
771  break;
772  default:
773  throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
774  }
775  statement.clearParameters();
776  statement.setString(1, loginName);
777  connection.executeUpdate(statement);
778  } catch (SQLException ex) {
779  throw new TskCoreException("Error inserting row in tsk_examiners. login name: " + loginName, ex);
780  } finally {
782  }
783  }
784 
792  private void populateHasChildrenMap(CaseDbConnection connection) throws TskCoreException {
793  long timestamp = System.currentTimeMillis();
794 
795  Statement statement = null;
796  ResultSet resultSet = null;
798  try {
799  statement = connection.createStatement();
800  resultSet = statement.executeQuery("select distinct par_obj_id from tsk_objects"); //NON-NLS
801 
802  synchronized (hasChildrenBitSetMap) {
803  while (resultSet.next()) {
804  setHasChildren(resultSet.getLong("par_obj_id"));
805  }
806  }
807  long delay = System.currentTimeMillis() - timestamp;
808  logger.log(Level.INFO, "Time to initialize parent node cache: {0} ms", delay); //NON-NLS
809  } catch (SQLException ex) {
810  throw new TskCoreException("Error populating parent node cache", ex);
811  } finally {
812  closeResultSet(resultSet);
813  closeStatement(statement);
815  }
816  }
817 
824  void addDataSourceToHasChildrenMap() throws TskCoreException {
825 
826  CaseDbConnection connection = connections.getConnection();
827  try {
828  populateHasChildrenMap(connection);
829  } finally {
830  if (connection != null) {
831  connection.close();
832  }
833  }
834  }
835 
845  private void updateDatabaseSchema(String dbPath) throws Exception {
846  CaseDbConnection connection = connections.getConnection();
847  ResultSet resultSet = null;
848  Statement statement = null;
850  try {
851  connection.beginTransaction();
852 
853  boolean hasMinorVersion = false;
854  ResultSet columns = connection.getConnection().getMetaData().getColumns(null, null, "tsk_db_info", "schema%");
855  while (columns.next()) {
856  if (columns.getString("COLUMN_NAME").equals("schema_minor_ver")) {
857  hasMinorVersion = true;
858  }
859  }
860 
861  // Get the schema version number of the case database from the tsk_db_info table.
862  int dbSchemaMajorVersion;
863  int dbSchemaMinorVersion = 0; //schemas before 7 have no minor version , default it to zero.
864 
865  statement = connection.createStatement();
866  resultSet = connection.executeQuery(statement, "SELECT schema_ver"
867  + (hasMinorVersion ? ", schema_minor_ver" : "")
868  + " FROM tsk_db_info"); //NON-NLS
869  if (resultSet.next()) {
870  dbSchemaMajorVersion = resultSet.getInt("schema_ver"); //NON-NLS
871  if (hasMinorVersion) {
872  //if there is a minor version column, use it, else default to zero.
873  dbSchemaMinorVersion = resultSet.getInt("schema_minor_ver"); //NON-NLS
874  }
875  } else {
876  throw new TskCoreException();
877  }
878  CaseDbSchemaVersionNumber dbSchemaVersion = new CaseDbSchemaVersionNumber(dbSchemaMajorVersion, dbSchemaMinorVersion);
879 
880  resultSet.close();
881  resultSet = null;
882  statement.close();
883  statement = null;
884  //check schema compatibility
885  if (false == CURRENT_DB_SCHEMA_VERSION.isCompatible(dbSchemaVersion)) {
886  //we cannot open a db with a major schema version higher than the current one.
887  throw new TskUnsupportedSchemaVersionException(
888  "Unsupported DB schema version " + dbSchemaVersion + ", the highest supported schema version is " + CURRENT_DB_SCHEMA_VERSION.getMajor() + ".X");
889  } else if (dbSchemaVersion.compareTo(CURRENT_DB_SCHEMA_VERSION) < 0) {
890  //The schema version is compatible,possibly after upgrades.
891 
892  if (null != dbPath) {
893  // Make a backup copy of the database. Client code can get the path of the backup
894  // using the getBackupDatabasePath() method.
895  String backupFilePath = dbPath + ".schemaVer" + dbSchemaVersion.toString() + ".backup"; //NON-NLS
896  copyCaseDB(backupFilePath);
897  dbBackupPath = backupFilePath;
898  }
899 
900  // ***CALL SCHEMA UPDATE METHODS HERE***
901  // Each method should examine the schema version passed to it and either:
902  // a. do nothing and return the schema version unchanged, or
903  // b. upgrade the database and return the schema version that the db was upgraded to.
904  dbSchemaVersion = updateFromSchema2toSchema3(dbSchemaVersion, connection);
905  dbSchemaVersion = updateFromSchema3toSchema4(dbSchemaVersion, connection);
906  dbSchemaVersion = updateFromSchema4toSchema5(dbSchemaVersion, connection);
907  dbSchemaVersion = updateFromSchema5toSchema6(dbSchemaVersion, connection);
908  dbSchemaVersion = updateFromSchema6toSchema7(dbSchemaVersion, connection);
909  dbSchemaVersion = updateFromSchema7toSchema7dot1(dbSchemaVersion, connection);
910  dbSchemaVersion = updateFromSchema7dot1toSchema7dot2(dbSchemaVersion, connection);
911  dbSchemaVersion = updateFromSchema7dot2toSchema8dot0(dbSchemaVersion, connection);
912  dbSchemaVersion = updateFromSchema8dot0toSchema8dot1(dbSchemaVersion, connection);
913  dbSchemaVersion = updateFromSchema8dot1toSchema8dot2(dbSchemaVersion, connection);
914  dbSchemaVersion = updateFromSchema8dot2toSchema8dot3(dbSchemaVersion, connection);
915  dbSchemaVersion = updateFromSchema8dot3toSchema8dot4(dbSchemaVersion, connection);
916  dbSchemaVersion = updateFromSchema8dot4toSchema8dot5(dbSchemaVersion, connection);
917  dbSchemaVersion = updateFromSchema8dot5toSchema8dot6(dbSchemaVersion, connection);
918  statement = connection.createStatement();
919  connection.executeUpdate(statement, "UPDATE tsk_db_info SET schema_ver = " + dbSchemaVersion.getMajor() + ", schema_minor_ver = " + dbSchemaVersion.getMinor()); //NON-NLS
920  connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value = " + dbSchemaVersion.getMajor() + " WHERE name = '" + SCHEMA_MAJOR_VERSION_KEY + "'"); //NON-NLS
921  connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value = " + dbSchemaVersion.getMinor() + " WHERE name = '" + SCHEMA_MINOR_VERSION_KEY + "'"); //NON-NLS
922  statement.close();
923  statement = null;
924  }
925 
926  connection.commitTransaction();
927  } catch (Exception ex) { // Cannot do exception multi-catch in Java 6, so use catch-all.
928  connection.rollbackTransaction();
929  throw ex;
930  } finally {
931  closeResultSet(resultSet);
932  closeStatement(statement);
933  connection.close();
935  }
936  }
937 
945  private void initDBSchemaCreationVersion(CaseDbConnection connection) throws SQLException {
946 
947  Statement statement = null;
948  ResultSet resultSet = null;
949  String createdSchemaMajorVersion = "0";
950  String createdSchemaMinorVersion = "0";
952  try {
953  statement = connection.createStatement();
954  resultSet = connection.executeQuery(statement, "SELECT name, value FROM tsk_db_info_extended");
955  while (resultSet.next()) {
956  String name = resultSet.getString("name");
957  if (name.equals(CREATION_SCHEMA_MAJOR_VERSION_KEY) || name.equals("CREATED_SCHEMA_MAJOR_VERSION")) {
958  createdSchemaMajorVersion = resultSet.getString("value");
959  } else if (name.equals(CREATION_SCHEMA_MINOR_VERSION_KEY) || name.equals("CREATED_SCHEMA_MINOR_VERSION")) {
960  createdSchemaMinorVersion = resultSet.getString("value");
961  }
962  }
963 
964  } finally {
965  closeResultSet(resultSet);
966  closeStatement(statement);
968  }
969 
970  caseDBSchemaCreationVersion = new CaseDbSchemaVersionNumber(Integer.parseInt(createdSchemaMajorVersion), Integer.parseInt(createdSchemaMinorVersion));
971  }
972 
982  public void copyCaseDB(String newDBPath) throws IOException {
983  if (dbPath.isEmpty()) {
984  throw new IOException("Copying case database files is not supported for this type of case database"); //NON-NLS
985  }
986  InputStream in = null;
987  OutputStream out = null;
989  try {
990  InputStream inFile = new FileInputStream(dbPath);
991  in = new BufferedInputStream(inFile);
992  OutputStream outFile = new FileOutputStream(newDBPath);
993  out = new BufferedOutputStream(outFile);
994  int bytesRead = in.read();
995  while (bytesRead != -1) {
996  out.write(bytesRead);
997  bytesRead = in.read();
998  }
999  } finally {
1000  try {
1001  if (in != null) {
1002  in.close();
1003  }
1004  if (out != null) {
1005  out.flush();
1006  out.close();
1007  }
1008  } catch (IOException e) {
1009  logger.log(Level.WARNING, "Could not close streams after db copy", e); //NON-NLS
1010  }
1012  }
1013  }
1014 
1018  private void logSQLiteJDBCDriverInfo() {
1019  try {
1020  SleuthkitCase.logger.info(String.format("sqlite-jdbc version %s loaded in %s mode", //NON-NLS
1021  SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode()
1022  ? "native" : "pure-java")); //NON-NLS
1023  } catch (Exception ex) {
1024  SleuthkitCase.logger.log(Level.SEVERE, "Error querying case database mode", ex);
1025  }
1026  }
1027 
1041  @SuppressWarnings("deprecation")
1042  private CaseDbSchemaVersionNumber updateFromSchema2toSchema3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1043  if (schemaVersion.getMajor() != 2) {
1044  return schemaVersion;
1045  }
1046  Statement statement = null;
1047  Statement updateStatement = null;
1048  ResultSet resultSet = null;
1050  try {
1051  statement = connection.createStatement();
1052 
1053  // Add new tables for tags.
1054  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
1055  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
1056  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
1057 
1058  // Add a new table for reports.
1059  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
1060 
1061  // Add new columns to the image info table.
1062  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN size INTEGER;"); //NON-NLS
1063  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN md5 TEXT;"); //NON-NLS
1064  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN display_name TEXT;"); //NON-NLS
1065 
1066  // Add a new column to the file system info table.
1067  statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN display_name TEXT;"); //NON-NLS
1068 
1069  // Add a new column to the file table.
1070  statement.execute("ALTER TABLE tsk_files ADD COLUMN meta_seq INTEGER;"); //NON-NLS
1071 
1072  // Add new columns and indexes to the attributes table and populate the
1073  // new column. Note that addition of the new column is a denormalization
1074  // to optimize attribute queries.
1075  statement.execute("ALTER TABLE blackboard_attributes ADD COLUMN artifact_type_id INTEGER NULL NOT NULL DEFAULT -1;"); //NON-NLS
1076  statement.execute("CREATE INDEX attribute_artifactTypeId ON blackboard_attributes(artifact_type_id);"); //NON-NLS
1077  statement.execute("CREATE INDEX attribute_valueText ON blackboard_attributes(value_text);"); //NON-NLS
1078  statement.execute("CREATE INDEX attribute_valueInt32 ON blackboard_attributes(value_int32);"); //NON-NLS
1079  statement.execute("CREATE INDEX attribute_valueInt64 ON blackboard_attributes(value_int64);"); //NON-NLS
1080  statement.execute("CREATE INDEX attribute_valueDouble ON blackboard_attributes(value_double);"); //NON-NLS
1081  resultSet = statement.executeQuery("SELECT attrs.artifact_id AS artifact_id, " //NON-NLS
1082  + "arts.artifact_type_id AS artifact_type_id " //NON-NLS
1083  + "FROM blackboard_attributes AS attrs " //NON-NLS
1084  + "INNER JOIN blackboard_artifacts AS arts " //NON-NLS
1085  + "WHERE attrs.artifact_id = arts.artifact_id;"); //NON-NLS
1086  updateStatement = connection.createStatement();
1087  while (resultSet.next()) {
1088  long artifactId = resultSet.getLong("artifact_id");
1089  int artifactTypeId = resultSet.getInt("artifact_type_id");
1090  updateStatement.executeUpdate(
1091  "UPDATE blackboard_attributes " //NON-NLS
1092  + "SET artifact_type_id = " + artifactTypeId //NON-NLS
1093  + " WHERE blackboard_attributes.artifact_id = " + artifactId + ";"); //NON-NLS
1094  }
1095  resultSet.close();
1096  resultSet = null;
1097 
1098  // Convert existing tag artifact and attribute rows to rows in the new tags tables.
1099  // TODO: This code depends on prepared statements that could evolve with
1100  // time, breaking this upgrade. The code that follows should be rewritten
1101  // to do everything with SQL specific to case database schema version 2.
1102  HashMap<String, TagName> tagNames = new HashMap<String, TagName>();
1103  for (BlackboardArtifact artifact : getBlackboardArtifacts(ARTIFACT_TYPE.TSK_TAG_FILE)) {
1104  Content content = getContentById(artifact.getObjectID());
1105  String name = ""; //NON-NLS
1106  String comment = ""; //NON-NLS
1107  ArrayList<BlackboardAttribute> attributes = getBlackboardAttributes(artifact);
1108  for (BlackboardAttribute attribute : attributes) {
1109  if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()) {
1110  name = attribute.getValueString();
1111  } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()) {
1112  comment = attribute.getValueString();
1113  }
1114  }
1115  if (!name.isEmpty()) {
1116  TagName tagName;
1117  if (tagNames.containsKey(name)) {
1118  tagName = tagNames.get(name);
1119  } else {
1120  tagName = addTagName(name, "", TagName.HTML_COLOR.NONE); //NON-NLS
1121  tagNames.put(name, tagName);
1122  }
1123  addContentTag(content, tagName, comment, 0, content.getSize() - 1);
1124  }
1125  }
1126  for (BlackboardArtifact artifact : getBlackboardArtifacts(ARTIFACT_TYPE.TSK_TAG_ARTIFACT)) {
1127  long taggedArtifactId = -1;
1128  String name = ""; //NON-NLS
1129  String comment = ""; //NON-NLS
1130  ArrayList<BlackboardAttribute> attributes = getBlackboardAttributes(artifact);
1131  for (BlackboardAttribute attribute : attributes) {
1132  if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()) {
1133  name = attribute.getValueString();
1134  } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID()) {
1135  comment = attribute.getValueString();
1136  } else if (attribute.getAttributeTypeID() == ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID()) {
1137  taggedArtifactId = attribute.getValueLong();
1138  }
1139  }
1140  if (taggedArtifactId != -1 && !name.isEmpty()) {
1141  TagName tagName;
1142  if (tagNames.containsKey(name)) {
1143  tagName = tagNames.get(name);
1144  } else {
1145  tagName = addTagName(name, "", TagName.HTML_COLOR.NONE); //NON-NLS
1146  tagNames.put(name, tagName);
1147  }
1148  addBlackboardArtifactTag(getBlackboardArtifact(taggedArtifactId), tagName, comment);
1149  }
1150  }
1151  statement.execute(
1152  "DELETE FROM blackboard_attributes WHERE artifact_id IN " //NON-NLS
1153  + "(SELECT artifact_id FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS
1154  + ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1155  + " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ");"); //NON-NLS
1156  statement.execute(
1157  "DELETE FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS
1158  + ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1159  + " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ";"); //NON-NLS
1160 
1161  return new CaseDbSchemaVersionNumber(3, 0);
1162  } finally {
1163  closeStatement(updateStatement);
1164  closeResultSet(resultSet);
1165  closeStatement(statement);
1166  connection.close();
1168  }
1169  }
1170 
1184  private CaseDbSchemaVersionNumber updateFromSchema3toSchema4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1185  if (schemaVersion.getMajor() != 3) {
1186  return schemaVersion;
1187  }
1188 
1189  Statement statement = null;
1190  ResultSet resultSet = null;
1191  Statement queryStatement = null;
1192  ResultSet queryResultSet = null;
1193  Statement updateStatement = null;
1195  try {
1196  // Add mime_type column to tsk_files table. Populate with general
1197  // info artifact file signature data.
1198  statement = connection.createStatement();
1199  updateStatement = connection.createStatement();
1200  statement.execute("ALTER TABLE tsk_files ADD COLUMN mime_type TEXT;");
1201  resultSet = statement.executeQuery("SELECT files.obj_id AS obj_id, attrs.value_text AS value_text "
1202  + "FROM tsk_files AS files, blackboard_attributes AS attrs, blackboard_artifacts AS arts "
1203  + "WHERE files.obj_id = arts.obj_id AND "
1204  + "arts.artifact_id = attrs.artifact_id AND "
1205  + "arts.artifact_type_id = 1 AND "
1206  + "attrs.attribute_type_id = 62");
1207  while (resultSet.next()) {
1208  updateStatement.executeUpdate(
1209  "UPDATE tsk_files " //NON-NLS
1210  + "SET mime_type = '" + resultSet.getString("value_text") + "' " //NON-NLS
1211  + "WHERE tsk_files.obj_id = " + resultSet.getInt("obj_id") + ";"); //NON-NLS
1212  }
1213  resultSet.close();
1214 
1215  // Add value_type column to blackboard_attribute_types table.
1216  statement.execute("ALTER TABLE blackboard_attribute_types ADD COLUMN value_type INTEGER NOT NULL DEFAULT -1;");
1217  resultSet = statement.executeQuery("SELECT * FROM blackboard_attribute_types AS types"); //NON-NLS
1218  while (resultSet.next()) {
1219  int attributeTypeId = resultSet.getInt("attribute_type_id");
1220  String attributeLabel = resultSet.getString("type_name");
1221  if (attributeTypeId < MIN_USER_DEFINED_TYPE_ID) {
1222  updateStatement.executeUpdate(
1223  "UPDATE blackboard_attribute_types " //NON-NLS
1224  + "SET value_type = " + ATTRIBUTE_TYPE.fromLabel(attributeLabel).getValueType().getType() + " " //NON-NLS
1225  + "WHERE blackboard_attribute_types.attribute_type_id = " + attributeTypeId + ";"); //NON-NLS
1226  }
1227  }
1228  resultSet.close();
1229 
1230  // Add a data_sources_info table.
1231  queryStatement = connection.createStatement();
1232  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));");
1233  resultSet = statement.executeQuery("SELECT * FROM tsk_objects WHERE par_obj_id IS NULL");
1234  while (resultSet.next()) {
1235  long objectId = resultSet.getLong("obj_id");
1236  String timeZone = "";
1237  queryResultSet = queryStatement.executeQuery("SELECT tzone FROM tsk_image_info WHERE obj_id = " + objectId);
1238  if (queryResultSet.next()) {
1239  timeZone = queryResultSet.getString("tzone");
1240  }
1241  queryResultSet.close();
1242  updateStatement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) "
1243  + "VALUES(" + objectId + ", '" + UUID.randomUUID().toString() + "' , '" + timeZone + "');");
1244  }
1245  resultSet.close();
1246 
1247  // Add data_source_obj_id column to the tsk_files table.
1248  //
1249  // NOTE: A new case database will have the following FK constraint:
1250  //
1251  // REFERENCES data_source_info (obj_id)
1252  //
1253  // The constraint is sacrificed here to avoid having to create and
1254  // populate a new tsk_files table.
1255  //
1256  // TODO: Do this right.
1257  statement.execute("ALTER TABLE tsk_files ADD COLUMN data_source_obj_id BIGINT NOT NULL DEFAULT -1;");
1258  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");
1259  while (resultSet.next()) {
1260  long fileId = resultSet.getLong("obj_id");
1261  long dataSourceId = getDataSourceObjectId(connection, fileId);
1262  updateStatement.executeUpdate("UPDATE tsk_files SET data_source_obj_id = " + dataSourceId + " WHERE obj_id = " + fileId + ";");
1263  }
1264  resultSet.close();
1265  statement.execute("CREATE TABLE ingest_module_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)"); //NON-NLS
1266  statement.execute("CREATE TABLE ingest_job_status_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)"); //NON-NLS
1267  if (this.dbType.equals(DbType.SQLITE)) {
1268  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
1269  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
1270  } else {
1271  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
1272  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
1273  }
1274 
1275  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
1276  initIngestModuleTypes(connection);
1277  initIngestStatusTypes(connection);
1278 
1279  return new CaseDbSchemaVersionNumber(4, 0);
1280 
1281  } finally {
1282  closeResultSet(queryResultSet);
1283  closeStatement(queryStatement);
1284  closeStatement(updateStatement);
1285  closeResultSet(resultSet);
1286  closeStatement(statement);
1288  }
1289  }
1290 
1304  private CaseDbSchemaVersionNumber updateFromSchema4toSchema5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1305  if (schemaVersion.getMajor() != 4) {
1306  return schemaVersion;
1307  }
1308 
1309  Statement statement = null;
1311  try {
1312  // Add the review_statuses lookup table.
1313  statement = connection.createStatement();
1314  statement.execute("CREATE TABLE review_statuses (review_status_id INTEGER PRIMARY KEY, review_status_name TEXT NOT NULL, display_name TEXT NOT NULL)");
1315 
1316  /*
1317  * Add review_status_id column to artifacts table.
1318  *
1319  * NOTE: For DBs created with schema 5 we define a foreign key
1320  * constraint on the review_status_column. We don't bother with this
1321  * for DBs updated to schema 5 because of limitations of the SQLite
1322  * ALTER TABLE command.
1323  */
1324  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN review_status_id INTEGER NOT NULL DEFAULT " + BlackboardArtifact.ReviewStatus.UNDECIDED.getID());
1325 
1326  // Add the encoding table
1327  statement.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL);");
1328  initEncodingTypes(connection);
1329 
1330  /*
1331  * This needs to be done due to a Autopsy/TSK out of synch problem.
1332  * Without this, it is possible to upgrade from version 4 to 5 and
1333  * then 5 to 6, but not from 4 to 6.
1334  */
1335  initReviewStatuses(connection);
1336 
1337  // Add encoding type column to tsk_files_path
1338  // This should really have the FOREIGN KEY constraint but there are problems
1339  // getting that to work, so we don't add it on this upgrade path.
1340  statement.execute("ALTER TABLE tsk_files_path ADD COLUMN encoding_type INTEGER NOT NULL DEFAULT 0;");
1341 
1342  return new CaseDbSchemaVersionNumber(5, 0);
1343 
1344  } finally {
1345  closeStatement(statement);
1347  }
1348  }
1349 
1363  private CaseDbSchemaVersionNumber updateFromSchema5toSchema6(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1364  if (schemaVersion.getMajor() != 5) {
1365  return schemaVersion;
1366  }
1367 
1368  /*
1369  * This upgrade fixes a bug where some releases had artifact review
1370  * status support in the case database and others did not.
1371  */
1372  Statement statement = null;
1373  ResultSet resultSet = null;
1375  try {
1376  /*
1377  * Add the review_statuses lookup table, if missing.
1378  */
1379  statement = connection.createStatement();
1380  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)");
1381 
1382  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM review_statuses"); //NON-NLS
1383  resultSet.next();
1384  if (resultSet.getLong("count") == 0) {
1385  /*
1386  * Add review_status_id column to artifacts table.
1387  *
1388  * NOTE: For DBs created with schema 5 or 6 we define a foreign
1389  * key constraint on the review_status_column. We don't bother
1390  * with this for DBs updated to schema 5 or 6 because of
1391  * limitations of the SQLite ALTER TABLE command.
1392  */
1393  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN review_status_id INTEGER NOT NULL DEFAULT " + BlackboardArtifact.ReviewStatus.UNDECIDED.getID());
1394  }
1395 
1396  return new CaseDbSchemaVersionNumber(6, 0);
1397 
1398  } finally {
1399  closeResultSet(resultSet);
1400  closeStatement(statement);
1402  }
1403  }
1404 
1418  private CaseDbSchemaVersionNumber updateFromSchema6toSchema7(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1419  if (schemaVersion.getMajor() != 6) {
1420  return schemaVersion;
1421  }
1422 
1423  /*
1424  * This upgrade adds an indexed extension column to the tsk_files table.
1425  */
1426  Statement statement = null;
1427  Statement updstatement = null;
1428  ResultSet resultSet = null;
1430  try {
1431  statement = connection.createStatement();
1432  updstatement = connection.createStatement();
1433  statement.execute("ALTER TABLE tsk_files ADD COLUMN extension TEXT");
1434 
1435  resultSet = connection.executeQuery(statement, "SELECT obj_id,name FROM tsk_files"); //NON-NLS
1436  while (resultSet.next()) {
1437  long objID = resultSet.getLong("obj_id");
1438  String name = resultSet.getString("name");
1439  updstatement.executeUpdate("UPDATE tsk_files SET extension = '" + escapeSingleQuotes(extractExtension(name)) + "' "
1440  + "WHERE obj_id = " + objID);
1441  }
1442 
1443  statement.execute("CREATE INDEX file_extension ON tsk_files ( extension )");
1444 
1445  // Add artifact_obj_id column to blackboard_artifacts table, data conversion for old versions isn't necesarry.
1446  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN artifact_obj_id INTEGER NOT NULL DEFAULT -1");
1447 
1448  return new CaseDbSchemaVersionNumber(7, 0);
1449 
1450  } finally {
1451  closeResultSet(resultSet);
1452  closeStatement(statement);
1453  closeStatement(updstatement);
1455  }
1456  }
1457 
1471  private CaseDbSchemaVersionNumber updateFromSchema7toSchema7dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1472  if (schemaVersion.getMajor() != 7) {
1473  return schemaVersion;
1474  }
1475 
1476  if (schemaVersion.getMinor() != 0) {
1477  return schemaVersion;
1478  }
1479 
1480  /*
1481  * This upgrade adds a minor version number column.
1482  */
1483  Statement statement = null;
1484  ResultSet resultSet = null;
1486  try {
1487  statement = connection.createStatement();
1488 
1489  //add the schema minor version number column.
1490  if (schemaVersion.getMinor() == 0) {
1491  //add the schema minor version number column.
1492  statement.execute("ALTER TABLE tsk_db_info ADD COLUMN schema_minor_ver INTEGER DEFAULT 1");
1493  }
1494  return new CaseDbSchemaVersionNumber(7, 1);
1495 
1496  } finally {
1497  closeResultSet(resultSet);
1498  closeStatement(statement);
1500  }
1501  }
1502 
1516  private CaseDbSchemaVersionNumber updateFromSchema7dot1toSchema7dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1517  if (schemaVersion.getMajor() != 7) {
1518  return schemaVersion;
1519  }
1520 
1521  if (schemaVersion.getMinor() != 1) {
1522  return schemaVersion;
1523  }
1524 
1525  Statement statement = null;
1526  Statement updstatement = null;
1527  ResultSet resultSet = null;
1529  try {
1530  //add the data_source_obj_id column to blackboard_artifacts.
1531  statement = connection.createStatement();
1532  statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN data_source_obj_id INTEGER NOT NULL DEFAULT -1");
1533 
1534  // populate data_source_obj_id for each artifact
1535  updstatement = connection.createStatement();
1536  resultSet = connection.executeQuery(statement, "SELECT artifact_id, obj_id FROM blackboard_artifacts"); //NON-NLS
1537  while (resultSet.next()) {
1538  long artifact_id = resultSet.getLong("artifact_id");
1539  long obj_id = resultSet.getLong("obj_id");
1540  long data_source_obj_id = getDataSourceObjectId(connection, obj_id);
1541  updstatement.executeUpdate("UPDATE blackboard_artifacts SET data_source_obj_id = " + data_source_obj_id + " "
1542  + "WHERE artifact_id = " + artifact_id);
1543  }
1544  closeResultSet(resultSet);
1545  closeStatement(statement);
1546  closeStatement(updstatement);
1547 
1548  /*
1549  * Add a knownStatus column to the tag_names table.
1550  */
1551  statement = connection.createStatement();
1552  statement.execute("ALTER TABLE tag_names ADD COLUMN knownStatus INTEGER NOT NULL DEFAULT " + TskData.FileKnown.UNKNOWN.getFileKnownValue());
1553 
1554  // Create account_types, accounts, and account_relationships table
1555  if (this.dbType.equals(DbType.SQLITE)) {
1556  statement.execute("CREATE TABLE account_types (account_type_id INTEGER PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
1557  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))");
1558  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))");
1559  } else {
1560  statement.execute("CREATE TABLE account_types (account_type_id BIGSERIAL PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
1561  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))");
1562  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))");
1563  }
1564 
1565  // Create indexes
1566  statement.execute("CREATE INDEX artifact_artifact_objID ON blackboard_artifacts(artifact_obj_id)");
1567  statement.execute("CREATE INDEX relationships_account1 ON account_relationships(account1_id)");
1568  statement.execute("CREATE INDEX relationships_account2 ON account_relationships(account2_id)");
1569  statement.execute("CREATE INDEX relationships_relationship_source_obj_id ON account_relationships(relationship_source_obj_id)");
1570  statement.execute("CREATE INDEX relationships_date_time ON account_relationships(date_time)");
1571  statement.execute("CREATE INDEX relationships_relationship_type ON account_relationships(relationship_type)");
1572  statement.execute("CREATE INDEX relationships_data_source_obj_id ON account_relationships(data_source_obj_id)");
1573 
1574  return new CaseDbSchemaVersionNumber(7, 2);
1575  } finally {
1576  closeResultSet(resultSet);
1577  closeStatement(statement);
1578  closeStatement(updstatement);
1580  }
1581  }
1582 
1596  private CaseDbSchemaVersionNumber updateFromSchema7dot2toSchema8dot0(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1597  if (schemaVersion.getMajor() != 7) {
1598  return schemaVersion;
1599  }
1600 
1601  if (schemaVersion.getMinor() != 2) {
1602  return schemaVersion;
1603  }
1604 
1605  Statement updateSchemaStatement = connection.createStatement();
1606  Statement getExistingReportsStatement = connection.createStatement();
1607  ResultSet resultSet = null;
1608  ResultSet existingReports = null;
1609 
1611  try {
1612  // Update the schema to turn report_id into an object id.
1613 
1614  // Unfortunately, SQLite doesn't support adding a constraint
1615  // to an existing table so we have to rename the old...
1616  updateSchemaStatement.execute("ALTER TABLE reports RENAME TO old_reports");
1617 
1618  // ...create the new...
1619  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))");
1620 
1621  // ...add the existing report records back...
1622  existingReports = getExistingReportsStatement.executeQuery("SELECT * FROM old_reports");
1623  while (existingReports.next()) {
1624  String path = existingReports.getString(2);
1625  long crtime = existingReports.getInt(3);
1626  String sourceModule = existingReports.getString(4);
1627  String reportName = existingReports.getString(5);
1628 
1629  PreparedStatement insertObjectStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OBJECT, Statement.RETURN_GENERATED_KEYS);
1630  insertObjectStatement.clearParameters();
1631  insertObjectStatement.setNull(1, java.sql.Types.BIGINT);
1632  insertObjectStatement.setLong(2, TskData.ObjectType.REPORT.getObjectType());
1633  connection.executeUpdate(insertObjectStatement);
1634  resultSet = insertObjectStatement.getGeneratedKeys();
1635  if (!resultSet.next()) {
1636  throw new TskCoreException(String.format("Failed to INSERT report %s (%s) in tsk_objects table", reportName, path));
1637  }
1638  long objectId = resultSet.getLong(1); //last_insert_rowid()
1639 
1640  // INSERT INTO reports (obj_id, path, crtime, src_module_name, display_name) VALUES (?, ?, ?, ?, ?)
1641  PreparedStatement insertReportStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_REPORT);
1642  insertReportStatement.clearParameters();
1643  insertReportStatement.setLong(1, objectId);
1644  insertReportStatement.setString(2, path);
1645  insertReportStatement.setLong(3, crtime);
1646  insertReportStatement.setString(4, sourceModule);
1647  insertReportStatement.setString(5, reportName);
1648  connection.executeUpdate(insertReportStatement);
1649  }
1650 
1651  // ...and drop the old table.
1652  updateSchemaStatement.execute("DROP TABLE old_reports");
1653 
1654  return new CaseDbSchemaVersionNumber(8, 0);
1655  } finally {
1656  closeResultSet(resultSet);
1657  closeResultSet(existingReports);
1658  closeStatement(updateSchemaStatement);
1659  closeStatement(getExistingReportsStatement);
1661  }
1662  }
1663 
1677  private CaseDbSchemaVersionNumber updateFromSchema8dot0toSchema8dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1678  if (schemaVersion.getMajor() != 8) {
1679  return schemaVersion;
1680  }
1681 
1682  if (schemaVersion.getMinor() != 0) {
1683  return schemaVersion;
1684  }
1685 
1687 
1688  try (Statement statement = connection.createStatement();) {
1689  // create examiners table
1690  if (this.dbType.equals(DbType.SQLITE)) {
1691  statement.execute("CREATE TABLE tsk_examiners (examiner_id INTEGER PRIMARY KEY, login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name) )");
1692  statement.execute("ALTER TABLE content_tags ADD COLUMN examiner_id INTEGER REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1693  statement.execute("ALTER TABLE blackboard_artifact_tags ADD COLUMN examiner_id INTEGER REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1694  } else {
1695  statement.execute("CREATE TABLE tsk_examiners (examiner_id BIGSERIAL PRIMARY KEY, login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))");
1696  statement.execute("ALTER TABLE content_tags ADD COLUMN examiner_id BIGINT REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1697  statement.execute("ALTER TABLE blackboard_artifact_tags ADD COLUMN examiner_id BIGINT REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1698  }
1699 
1700  return new CaseDbSchemaVersionNumber(8, 1);
1701  } finally {
1703  }
1704  }
1705 
1719  private CaseDbSchemaVersionNumber updateFromSchema8dot1toSchema8dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1720  if (schemaVersion.getMajor() != 8) {
1721  return schemaVersion;
1722  }
1723 
1724  if (schemaVersion.getMinor() != 1) {
1725  return schemaVersion;
1726  }
1727 
1729 
1730  try (Statement statement = connection.createStatement();) {
1731  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN sha1 TEXT DEFAULT NULL");
1732  statement.execute("ALTER TABLE tsk_image_info ADD COLUMN sha256 TEXT DEFAULT NULL");
1733 
1734  statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_details TEXT");
1735 
1736  /*
1737  * Add new tsk_db_extended_info table with TSK version, creation
1738  * time schema and schema version numbers as the initial data. The
1739  * creation time schema version is set to 0, 0 to indicate that it
1740  * is not known.
1741  */
1742  statement.execute("CREATE TABLE tsk_db_info_extended (name TEXT PRIMARY KEY, value TEXT NOT NULL)");
1743  ResultSet result = statement.executeQuery("SELECT tsk_ver FROM tsk_db_info");
1744  result.next();
1745  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + TSK_VERSION_KEY + "', '" + result.getLong("tsk_ver") + "')");
1746  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + SCHEMA_MAJOR_VERSION_KEY + "', '8')");
1747  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + SCHEMA_MINOR_VERSION_KEY + "', '2')");
1748  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '0')");
1749  statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + CREATION_SCHEMA_MINOR_VERSION_KEY + "', '0')");
1750 
1751  String primaryKeyType;
1752  switch (getDatabaseType()) {
1753  case POSTGRESQL:
1754  primaryKeyType = "BIGSERIAL";
1755  break;
1756  case SQLITE:
1757  primaryKeyType = "INTEGER";
1758  break;
1759  default:
1760  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1761  }
1762 
1763  //create and initialize tsk_event_types tables
1764  statement.execute("CREATE TABLE tsk_event_types ("
1765  + " event_type_id " + primaryKeyType + " PRIMARY KEY, "
1766  + " display_name TEXT UNIQUE NOT NULL, "
1767  + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
1768  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1769  + " values( 0, 'Event Types', null)");
1770  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1771  + " values(1, 'File System', 0)");
1772  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1773  + " values(2, 'Web Activity', 0)");
1774  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1775  + " values(3, 'Misc Types', 0)");
1776  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1777  + " values(4, 'Modified', 1)");
1778  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1779  + " values(5, 'Accessed', 1)");
1780  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1781  + " values(6, 'Created', 1)");
1782  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1783  + " values(7, 'Changed', 1)");
1784 
1785  //create tsk_events tables
1786  statement.execute("CREATE TABLE tsk_event_descriptions ("
1787  + " event_description_id " + primaryKeyType + " PRIMARY KEY, "
1788  + " full_description TEXT NOT NULL, "
1789  + " med_description TEXT, "
1790  + " short_description TEXT,"
1791  + " data_source_obj_id BIGINT NOT NULL, "
1792  + " file_obj_id BIGINT NOT NULL, "
1793  + " artifact_id BIGINT, "
1794  + " hash_hit INTEGER NOT NULL, " //boolean
1795  + " tagged INTEGER NOT NULL, " //boolean
1796  + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
1797  + " FOREIGN KEY(file_obj_id) REFERENCES tsk_files(obj_id), "
1798  + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
1799  );
1800 
1801  statement.execute("CREATE TABLE tsk_events ( "
1802  + " event_id " + primaryKeyType + " PRIMARY KEY, "
1803  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
1804  + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
1805  + " time INTEGER NOT NULL) "
1806  );
1807 
1808  //create tsk_events indices
1809  statement.execute("CREATE INDEX events_time ON tsk_events(time)");
1810  statement.execute("CREATE INDEX events_type ON tsk_events(event_type_id)");
1811  statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
1812  statement.execute("CREATE INDEX events_file_obj_id ON tsk_event_descriptions(file_obj_id) ");
1813  statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
1814  statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
1815  return new CaseDbSchemaVersionNumber(8, 2);
1816 
1817  } finally {
1819  }
1820  }
1821 
1835  private CaseDbSchemaVersionNumber updateFromSchema8dot2toSchema8dot3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1836  if (schemaVersion.getMajor() != 8) {
1837  return schemaVersion;
1838  }
1839 
1840  if (schemaVersion.getMinor() != 2) {
1841  return schemaVersion;
1842  }
1843 
1845 
1846  ResultSet resultSet = null;
1847 
1848  try (Statement statement = connection.createStatement();) {
1849 
1850  // Add the uniqueness constraint to the tsk_event and tsk_event_description tables.
1851  // Unfortunately, SQLite doesn't support adding a constraint
1852  // to an existing table so we have to rename the old...
1853  String primaryKeyType;
1854  switch (getDatabaseType()) {
1855  case POSTGRESQL:
1856  primaryKeyType = "BIGSERIAL";
1857  break;
1858  case SQLITE:
1859  primaryKeyType = "INTEGER";
1860  break;
1861  default:
1862  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1863  }
1864 
1865  //create and initialize tsk_event_types tables which may or may not exist
1866  statement.execute("CREATE TABLE IF NOT EXISTS tsk_event_types ("
1867  + " event_type_id " + primaryKeyType + " PRIMARY KEY, "
1868  + " display_name TEXT UNIQUE NOT NULL, "
1869  + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
1870 
1871  resultSet = statement.executeQuery("SELECT * from tsk_event_types");
1872 
1873  // If there is something in resultSet then the table must have previously
1874  // existing therefore there is not need to populate
1875  if (!resultSet.next()) {
1876 
1877  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1878  + " values( 0, 'Event Types', null)");
1879  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1880  + " values(1, 'File System', 0)");
1881  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1882  + " values(2, 'Web Activity', 0)");
1883  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1884  + " values(3, 'Misc Types', 0)");
1885  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1886  + " values(4, 'Modified', 1)");
1887  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1888  + " values(5, 'Accessed', 1)");
1889  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1890  + " values(6, 'Created', 1)");
1891  statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
1892  + " values(7, 'Changed', 1)");
1893  }
1894 
1895  // Delete the old table that may have been created with the upgrade
1896  // from 8.1 to 8.2.
1897  statement.execute("DROP TABLE IF EXISTS tsk_events");
1898 
1899  // Delete the old table that may have been created with the upgrade
1900  // from 8.1 to 8.2
1901  statement.execute("DROP TABLE IF EXISTS tsk_event_descriptions");
1902 
1903  //create new tsk_event_description table
1904  statement.execute("CREATE TABLE tsk_event_descriptions ("
1905  + " event_description_id " + primaryKeyType + " PRIMARY KEY, "
1906  + " full_description TEXT NOT NULL, "
1907  + " med_description TEXT, "
1908  + " short_description TEXT,"
1909  + " data_source_obj_id BIGINT NOT NULL, "
1910  + " file_obj_id BIGINT NOT NULL, "
1911  + " artifact_id BIGINT, "
1912  + " hash_hit INTEGER NOT NULL, " //boolean
1913  + " tagged INTEGER NOT NULL, " //boolean
1914  + " UNIQUE(full_description, file_obj_id, artifact_id), "
1915  + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
1916  + " FOREIGN KEY(file_obj_id) REFERENCES tsk_files(obj_id), "
1917  + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
1918  );
1919 
1920  // create a new table
1921  statement.execute("CREATE TABLE tsk_events ( "
1922  + " event_id " + primaryKeyType + " PRIMARY KEY, "
1923  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
1924  + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
1925  + " time INTEGER NOT NULL, "
1926  + " UNIQUE (event_type_id, event_description_id, time))"
1927  );
1928 
1929  // Fix mistakenly set names in tsk_db_info_extended
1930  statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MAJOR_VERSION' WHERE name = 'CREATED_SCHEMA_MAJOR_VERSION'");
1931  statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MINOR_VERSION' WHERE name = 'CREATED_SCHEMA_MINOR_VERSION'");
1932 
1933  return new CaseDbSchemaVersionNumber(8, 3);
1934  } finally {
1935  closeResultSet(resultSet);
1937  }
1938  }
1939 
1961  private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1962  if (schemaVersion.getMajor() != 8) {
1963  return schemaVersion;
1964  }
1965 
1966  if (schemaVersion.getMinor() != 3) {
1967  return schemaVersion;
1968  }
1969 
1970  Statement statement = connection.createStatement();
1971  ResultSet results = null;
1972 
1974  try {
1975  // This is a bug fix update for a misnamed column in tsk_event_descriptions in
1976  // the previous update code.
1977  if (null == getDatabaseType()) {
1978  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1979  }
1980 
1981  switch (getDatabaseType()) {
1982  case POSTGRESQL:
1983  // Check if the misnamed column is present
1984  results = statement.executeQuery("SELECT column_name FROM information_schema.columns "
1985  + "WHERE table_name='tsk_event_descriptions' and column_name='file_obj_id'");
1986  if (results.next()) {
1987  // In PostgreSQL we can rename the column if it exists
1988  statement.execute("ALTER TABLE tsk_event_descriptions "
1989  + "RENAME COLUMN file_obj_id TO content_obj_id");
1990 
1991  // 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
1992  // Fix the schema, preserving any data if exists.
1993  statement.execute("CREATE TABLE temp_tsk_events ( "
1994  + " event_id BIGSERIAL PRIMARY KEY, "
1995  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
1996  + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id),"
1997  + " time BIGINT NOT NULL, "
1998  + " UNIQUE (event_type_id, event_description_id, time))"
1999  );
2000 
2001  // Copy the data
2002  statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, "
2003  + "event_description_id, time) SELECT * FROM tsk_events");
2004 
2005  // Drop the old table
2006  statement.execute("DROP TABLE tsk_events");
2007 
2008  // Rename the new table
2009  statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events");
2010 
2011  //create tsk_events indices that were skipped in the 8.2 to 8.3 update code
2012  statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2013  statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) ");
2014  statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2015  statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2016  statement.execute("CREATE INDEX events_time ON tsk_events(time) ");
2017  }
2018  break;
2019  case SQLITE:
2020  boolean hasMisnamedColumn = false;
2021  results = statement.executeQuery("pragma table_info('tsk_event_descriptions')");
2022  while (results.next()) {
2023  if (results.getString("name") != null && results.getString("name").equals("file_obj_id")) {
2024  hasMisnamedColumn = true;
2025  break;
2026  }
2027  }
2028 
2029  if (hasMisnamedColumn) {
2030  // Since we can't rename the column we'll need to make new tables and copy the data
2031  statement.execute("CREATE TABLE temp_tsk_event_descriptions ("
2032  + " event_description_id INTEGER PRIMARY KEY, "
2033  + " full_description TEXT NOT NULL, "
2034  + " med_description TEXT, "
2035  + " short_description TEXT,"
2036  + " data_source_obj_id BIGINT NOT NULL, "
2037  + " content_obj_id BIGINT NOT NULL, "
2038  + " artifact_id BIGINT, "
2039  + " hash_hit INTEGER NOT NULL, " //boolean
2040  + " tagged INTEGER NOT NULL, " //boolean
2041  + " UNIQUE(full_description, content_obj_id, artifact_id), "
2042  + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
2043  + " FOREIGN KEY(content_obj_id) REFERENCES tsk_files(obj_id), "
2044  + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
2045  );
2046 
2047  statement.execute("CREATE TABLE temp_tsk_events ( "
2048  + " event_id INTEGER PRIMARY KEY, "
2049  + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
2050  + " event_description_id BIGINT NOT NULL REFERENCES temp_tsk_event_descriptions(event_description_id),"
2051  + " time INTEGER NOT NULL, "
2052  + " UNIQUE (event_type_id, event_description_id, time))"
2053  );
2054 
2055  // Copy the data
2056  statement.execute("INSERT INTO temp_tsk_event_descriptions(event_description_id, full_description, "
2057  + "med_description, short_description, data_source_obj_id, content_obj_id, artifact_id, "
2058  + "hash_hit, tagged) SELECT * FROM tsk_event_descriptions");
2059 
2060  statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, "
2061  + "event_description_id, time) SELECT * FROM tsk_events");
2062 
2063  // Drop the old tables
2064  statement.execute("DROP TABLE tsk_events");
2065  statement.execute("DROP TABLE tsk_event_descriptions");
2066 
2067  // Rename the new tables
2068  statement.execute("ALTER TABLE temp_tsk_event_descriptions RENAME TO tsk_event_descriptions");
2069  statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events");
2070 
2071  //create tsk_events indices
2072  statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2073  statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) ");
2074  statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2075  statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2076  statement.execute("CREATE INDEX events_time ON tsk_events(time) ");
2077  }
2078  break;
2079  default:
2080  throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
2081  }
2082 
2083  // create pool info table
2084  if (this.dbType.equals(DbType.SQLITE)) {
2085  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)");
2086  } else {
2087  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)");
2088  }
2089 
2090  // Add new account types for newly supported messaging applications, if they dont exists already.
2091  insertAccountTypeIfNotExists(statement, "IMO", "IMO");
2092  insertAccountTypeIfNotExists(statement, "LINE", "LINE");
2093  insertAccountTypeIfNotExists(statement, "SKYPE", "Skype");
2094  insertAccountTypeIfNotExists(statement, "TANGO", "Tango");
2095  insertAccountTypeIfNotExists(statement, "TEXTNOW", "TextNow");
2096  insertAccountTypeIfNotExists(statement, "THREEMA", "ThreeMa");
2097  insertAccountTypeIfNotExists(statement, "VIBER", "Viber");
2098  insertAccountTypeIfNotExists(statement, "XENDER", "Xender");
2099  insertAccountTypeIfNotExists(statement, "ZAPYA", "Zapya");
2100  insertAccountTypeIfNotExists(statement, "SHAREIT", "ShareIt");
2101 
2102  return new CaseDbSchemaVersionNumber(8, 4);
2103  } finally {
2104  closeResultSet(results);
2105  closeStatement(statement);
2107  }
2108  }
2109 
2110  private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2111  if (schemaVersion.getMajor() != 8) {
2112  return schemaVersion;
2113  }
2114 
2115  if (schemaVersion.getMinor() != 4) {
2116  return schemaVersion;
2117  }
2118 
2119  Statement statement = connection.createStatement();
2121  try {
2122  switch (getDatabaseType()) {
2123  case POSTGRESQL:
2124  statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id BIGSERIAL PRIMARY KEY, name TEXT UNIQUE)");
2125  statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id BIGINT REFERENCES tsk_tag_sets(tag_set_id)");
2126  break;
2127  case SQLITE:
2128  statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id INTEGER PRIMARY KEY, name TEXT UNIQUE)");
2129  statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id INTEGER REFERENCES tsk_tag_sets(tag_set_id)");
2130  break;
2131  }
2132 
2133  statement.execute("ALTER TABLE tag_names ADD COLUMN rank INTEGER");
2134 
2135  String insertStmt = "INSERT INTO tsk_tag_sets (name) VALUES ('Project VIC')";
2136  if (getDatabaseType() == DbType.POSTGRESQL) {
2137  statement.execute(insertStmt, Statement.RETURN_GENERATED_KEYS);
2138  } else {
2139  statement.execute(insertStmt);
2140  }
2141  try (ResultSet resultSet = statement.getGeneratedKeys()) {
2142  if (resultSet != null && resultSet.next()) {
2143  int tagSetId = resultSet.getInt(1);
2144 
2145  String updateQuery = "UPDATE tag_names SET tag_set_id = %d, color = '%s', rank = %d, display_name = '%s' WHERE display_name = '%s'";
2146  statement.executeUpdate(String.format(updateQuery, tagSetId, "Red", 1, "Child Exploitation (Illegal)", "CAT-1: Child Exploitation (Illegal)"));
2147  statement.executeUpdate(String.format(updateQuery, tagSetId, "Lime", 2, "Child Exploitation (Non-Illegal/Age Difficult)", "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)"));
2148  statement.executeUpdate(String.format(updateQuery, tagSetId, "Yellow", 3, "CGI/Animation (Child Exploitive)", "CAT-3: CGI/Animation (Child Exploitive)"));
2149  statement.executeUpdate(String.format(updateQuery, tagSetId, "Purple", 4, "Exemplar/Comparison (Internal Use Only)", "CAT-4: Exemplar/Comparison (Internal Use Only)"));
2150  statement.executeUpdate(String.format(updateQuery, tagSetId, "Fuchsia", 5, "Non-pertinent", "CAT-5: Non-pertinent"));
2151 
2152  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')";
2153  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')";
2154  String deleteCat0 = "DELETE FROM tag_names WHERE display_name = 'CAT-0: Uncategorized'";
2155  statement.executeUpdate(deleteContentTag);
2156  statement.executeUpdate(deleteArtifactTag);
2157  statement.executeUpdate(deleteCat0);
2158 
2159  } else {
2160  throw new TskCoreException("Failed to retrieve the default tag_set_id from DB");
2161  }
2162  }
2163 
2164  // Add data_source_obj_id column to the tsk_files table. For newly created cases
2165  // this column will have a foreign key constraint on the data_source_info table.
2166  // There does not seem to be a reasonable way to do this in an upgrade,
2167  // so upgraded cases will be missing the foreign key.
2168  switch (getDatabaseType()) {
2169  case POSTGRESQL:
2170  statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN data_source_obj_id BIGINT NOT NULL DEFAULT -1;");
2171  break;
2172  case SQLITE:
2173  statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN data_source_obj_id INTEGER NOT NULL DEFAULT -1;");
2174  break;
2175  }
2176  Statement updateStatement = connection.createStatement();
2177  try (ResultSet resultSet = statement.executeQuery("SELECT obj_id FROM tsk_fs_info")) {
2178  while (resultSet.next()) {
2179  long fsId = resultSet.getLong("obj_id");
2180  long dataSourceId = getDataSourceObjectId(connection, fsId);
2181  updateStatement.executeUpdate("UPDATE tsk_fs_info SET data_source_obj_id = " + dataSourceId + " WHERE obj_id = " + fsId + ";");
2182  }
2183  } finally {
2184  closeStatement(updateStatement);
2185  }
2186 
2187  return new CaseDbSchemaVersionNumber(8, 5);
2188 
2189  } finally {
2190  closeStatement(statement);
2192  }
2193  }
2194 
2195  private CaseDbSchemaVersionNumber updateFromSchema8dot5toSchema8dot6(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2196  if (schemaVersion.getMajor() != 8) {
2197  return schemaVersion;
2198  }
2199 
2200  if (schemaVersion.getMinor() != 5) {
2201  return schemaVersion;
2202  }
2203 
2204  Statement statement = connection.createStatement();
2206  try {
2207  statement.execute("ALTER TABLE tsk_files ADD COLUMN sha256 TEXT");
2208 
2209  return new CaseDbSchemaVersionNumber(8, 6);
2210 
2211  } finally {
2212  closeStatement(statement);
2214  }
2215  }
2216 
2228  private void insertAccountTypeIfNotExists(Statement statement, String type_name, String display_name) throws TskCoreException, SQLException {
2229 
2230  String insertSQL = String.format("INTO account_types(type_name, display_name) VALUES ('%s', '%s')", type_name, display_name);
2231  switch (getDatabaseType()) {
2232  case POSTGRESQL:
2233  insertSQL = "INSERT " + insertSQL + " ON CONFLICT DO NOTHING"; //NON-NLS
2234  break;
2235  case SQLITE:
2236  insertSQL = "INSERT OR IGNORE " + insertSQL;
2237  break;
2238  default:
2239  throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
2240  }
2241  statement.execute(insertSQL); //NON-NLS
2242  }
2243 
2251  static String extractExtension(final String fileName) {
2252  String ext;
2253  int i = fileName.lastIndexOf(".");
2254  // > 0 because we assume it's not an extension if period is the first character
2255  if ((i > 0) && ((i + 1) < fileName.length())) {
2256  ext = fileName.substring(i + 1);
2257  } else {
2258  return "";
2259  }
2260  // we added this at one point to deal with files that had crazy names based on URLs
2261  // it's too hard though to clean those up and not mess up basic extensions though.
2262  // We need to add '-' to the below if we use it again
2263  // String[] findNonAlphanumeric = ext.split("[^a-zA-Z0-9_]");
2264  // if (findNonAlphanumeric.length > 1) {
2265  // ext = findNonAlphanumeric[0];
2266  // }
2267  return ext.toLowerCase();
2268  }
2269 
2280  @Deprecated
2281  public int getSchemaVersion() {
2282  return getDBSchemaVersion().getMajor();
2283  }
2284 
2291  return CURRENT_DB_SCHEMA_VERSION;
2292  }
2293 
2301  return caseDBSchemaCreationVersion;
2302  }
2303 
2310  return this.dbType;
2311  }
2312 
2319  public String getBackupDatabasePath() {
2320  return dbBackupPath;
2321  }
2322 
2337  public CaseDbTransaction beginTransaction() throws TskCoreException {
2338  return new CaseDbTransaction(this, connections.getConnection());
2339  }
2340 
2346  public String getDatabaseName() {
2347  return databaseName;
2348  }
2349 
2356  public String getDbDirPath() {
2357  return caseDirPath;
2358  }
2359 
2366  if (dbType == DbType.SQLITE) {
2367  rwLock.writeLock().lock();
2368  }
2369  }
2370 
2377  if (dbType == DbType.SQLITE) {
2378  rwLock.writeLock().unlock();
2379  }
2380  }
2381 
2388  if (dbType == DbType.SQLITE) {
2389  rwLock.readLock().lock();
2390  }
2391  }
2392 
2399  if (dbType == DbType.SQLITE) {
2400  rwLock.readLock().unlock();
2401  }
2402  }
2403 
2413  public static SleuthkitCase openCase(String dbPath) throws TskCoreException {
2414  try {
2415  final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath);
2416  return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE);
2418  //don't wrap in new TskCoreException
2419  throw ex;
2420  } catch (Exception ex) {
2421  throw new TskCoreException("Failed to open case database at " + dbPath, ex);
2422  }
2423  }
2424 
2436  public static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir) throws TskCoreException {
2437  try {
2438  /*
2439  * The flow of this method involves trying to open case and if
2440  * successful, return that case. If unsuccessful, an exception is
2441  * thrown. We catch any exceptions, and use tryConnect() to attempt
2442  * to obtain further information about the error. If tryConnect() is
2443  * unable to successfully connect, tryConnect() will throw a
2444  * TskCoreException with a message containing user-level error
2445  * reporting. If tryConnect() is able to connect, flow continues and
2446  * we rethrow the original exception obtained from trying to create
2447  * the case. In this way, we obtain more detailed information if we
2448  * are able, but do not lose any information if unable.
2449  */
2450  final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info);
2451  return new SleuthkitCase(info.getHost(), Integer.parseInt(info.getPort()), databaseName, info.getUserName(), info.getPassword(), caseHandle, caseDir, info.getDbType());
2452  } catch (PropertyVetoException exp) {
2453  // In this case, the JDBC driver doesn't support PostgreSQL. Use the generic message here.
2454  throw new TskCoreException(exp.getMessage(), exp);
2456  //don't wrap in new TskCoreException
2457  throw ex;
2458  } catch (Exception exp) {
2459  tryConnect(info); // attempt to connect, throw with user-friendly message if unable
2460  throw new TskCoreException(exp.getMessage(), exp); // throw with generic message if tryConnect() was successful
2461  }
2462  }
2463 
2473  public static SleuthkitCase newCase(String dbPath) throws TskCoreException {
2474  try {
2475  CaseDatabaseFactory factory = new CaseDatabaseFactory(dbPath);
2476  factory.createCaseDatabase();
2477 
2478  SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath);
2479  return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE);
2480  } catch (Exception ex) {
2481  throw new TskCoreException("Failed to create case database at " + dbPath, ex);
2482  }
2483  }
2484 
2500  public static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath) throws TskCoreException {
2501  String databaseName = createCaseDataBaseName(caseName);
2502  try {
2515  CaseDatabaseFactory factory = new CaseDatabaseFactory(databaseName, info);
2516  factory.createCaseDatabase();
2517 
2518  final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info);
2519  return new SleuthkitCase(info.getHost(), Integer.parseInt(info.getPort()),
2520  databaseName, info.getUserName(), info.getPassword(), caseHandle, caseDirPath, info.getDbType());
2521  } catch (PropertyVetoException exp) {
2522  // In this case, the JDBC driver doesn't support PostgreSQL. Use the generic message here.
2523  throw new TskCoreException(exp.getMessage(), exp);
2524  } catch (Exception exp) {
2525  tryConnect(info); // attempt to connect, throw with user-friendly message if unable
2526  throw new TskCoreException(exp.getMessage(), exp); // throw with generic message if tryConnect() was successful
2527  }
2528  }
2529 
2539  private static String createCaseDataBaseName(String candidateDbName) {
2540  String dbName;
2541  if (!candidateDbName.isEmpty()) {
2542  /*
2543  * Replace all non-ASCII characters.
2544  */
2545  dbName = candidateDbName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS
2546 
2547  /*
2548  * Replace all control characters.
2549  */
2550  dbName = dbName.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS
2551 
2552  /*
2553  * Replace /, \, :, ?, space, ' ".
2554  */
2555  dbName = dbName.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS
2556 
2557  /*
2558  * Make it all lowercase.
2559  */
2560  dbName = dbName.toLowerCase();
2561 
2562  /*
2563  * Must start with letter or underscore. If not, prepend an
2564  * underscore.
2565  */
2566  if ((dbName.length() > 0 && !(Character.isLetter(dbName.codePointAt(0))) && !(dbName.codePointAt(0) == '_'))) {
2567  dbName = "_" + dbName;
2568  }
2569 
2570  /*
2571  * Truncate to 63 - 16 = 47 chars to accomodate a timestamp for
2572  * uniqueness.
2573  */
2574  if (dbName.length() > MAX_DB_NAME_LEN_BEFORE_TIMESTAMP) {
2575  dbName = dbName.substring(0, MAX_DB_NAME_LEN_BEFORE_TIMESTAMP);
2576  }
2577 
2578  } else {
2579  /*
2580  * Must start with letter or underscore.
2581  */
2582  dbName = "_";
2583  }
2584  /*
2585  * Add the time stmap.
2586  */
2587  SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
2588  Date date = new Date();
2589  dbName = dbName + "_" + dateFormat.format(date);
2590 
2591  return dbName;
2592  }
2593 
2601  public Examiner getCurrentExaminer() throws TskCoreException {
2602 
2603  // return cached value if there's one
2604  if (cachedCurrentExaminer != null) {
2605  return cachedCurrentExaminer;
2606  }
2607  String loginName = System.getProperty("user.name");
2608  if (loginName == null || loginName.isEmpty()) {
2609  throw new TskCoreException("Failed to determine logged in user name.");
2610  }
2611 
2612  CaseDbConnection connection = connections.getConnection();
2614  ResultSet resultSet = null;
2615  try {
2616  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_EXAMINER_BY_LOGIN_NAME);
2617  statement.clearParameters();
2618  statement.setString(1, loginName);
2619  resultSet = connection.executeQuery(statement);
2620  if (resultSet.next()) {
2621  cachedCurrentExaminer = new Examiner(resultSet.getLong("examiner_id"), resultSet.getString("login_name"), resultSet.getString("display_name"));
2622  return cachedCurrentExaminer;
2623  } else {
2624  throw new TskCoreException("Error getting examaminer for name = " + loginName);
2625  }
2626 
2627  } catch (SQLException ex) {
2628  throw new TskCoreException("Error getting examaminer for name = " + loginName, ex);
2629  } finally {
2630  closeResultSet(resultSet);
2631  connection.close();
2633  }
2634 
2635  }
2636 
2646  Examiner getExaminerById(long id) throws TskCoreException {
2647 
2648  CaseDbConnection connection = connections.getConnection();
2650  ResultSet resultSet = null;
2651  try {
2652  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_EXAMINER_BY_ID);
2653  statement.clearParameters();
2654  statement.setLong(1, id);
2655  resultSet = connection.executeQuery(statement);
2656  if (resultSet.next()) {
2657  return new Examiner(resultSet.getLong("examiner_id"), resultSet.getString("login_name"), resultSet.getString("full_name"));
2658  } else {
2659  throw new TskCoreException("Error getting examaminer for id = " + id);
2660  }
2661  } catch (SQLException ex) {
2662  throw new TskCoreException("Error getting examaminer for id = " + id, ex);
2663  } finally {
2664  closeResultSet(resultSet);
2665  connection.close();
2667  }
2668  }
2669 
2687  public AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath) {
2688  return this.caseHandle.initAddImageProcess(timeZone, addUnallocSpace, noFatFsOrphans, imageCopyPath, this);
2689  }
2690 
2699  public List<Content> getRootObjects() throws TskCoreException {
2700  CaseDbConnection connection = connections.getConnection();
2702  Statement s = null;
2703  ResultSet rs = null;
2704  try {
2705  s = connection.createStatement();
2706  rs = connection.executeQuery(s, "SELECT obj_id, type FROM tsk_objects " //NON-NLS
2707  + "WHERE par_obj_id IS NULL"); //NON-NLS
2708  Collection<ObjectInfo> infos = new ArrayList<ObjectInfo>();
2709  while (rs.next()) {
2710  infos.add(new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")))); //NON-NLS
2711  }
2712 
2713  List<Content> rootObjs = new ArrayList<Content>();
2714  for (ObjectInfo i : infos) {
2715  if (null != i.type) {
2716  switch (i.type) {
2717  case IMG:
2718  rootObjs.add(getImageById(i.id));
2719  break;
2720  case ABSTRACTFILE:
2721  // Check if virtual dir for local files.
2722  AbstractFile af = getAbstractFileById(i.id);
2723  if (af instanceof VirtualDirectory) {
2724  rootObjs.add(af);
2725  } else {
2726  throw new TskCoreException("Parentless object has wrong type to be a root (ABSTRACTFILE, but not VIRTUAL_DIRECTORY: " + i.type);
2727  }
2728  break;
2729  case REPORT:
2730  break;
2731  default:
2732  throw new TskCoreException("Parentless object has wrong type to be a root: " + i.type);
2733  }
2734  }
2735  }
2736  return rootObjs;
2737  } catch (SQLException ex) {
2738  throw new TskCoreException("Error getting root objects", ex);
2739  } finally {
2740  closeResultSet(rs);
2741  closeStatement(s);
2742  connection.close();
2744  }
2745  }
2746 
2758  List<Long> getDataSourceObjIds(String deviceId) throws TskCoreException {
2759 
2760  // check cached map first
2761  synchronized (deviceIdToDatasourceObjIdMap) {
2762  if (deviceIdToDatasourceObjIdMap.containsKey(deviceId)) {
2763  return new ArrayList<Long>(deviceIdToDatasourceObjIdMap.get(deviceId));
2764  }
2765 
2766  CaseDbConnection connection = connections.getConnection();
2768  Statement s = null;
2769  ResultSet rs = null;
2770  try {
2771  s = connection.createStatement();
2772  rs = connection.executeQuery(s, "SELECT obj_id FROM data_source_info WHERE device_id = '" + deviceId + "'"); //NON-NLS
2773  List<Long> dataSourceObjIds = new ArrayList<Long>();
2774  while (rs.next()) {
2775  dataSourceObjIds.add(rs.getLong("obj_id"));
2776 
2777  // Add to map of deviceID to data_source_obj_id.
2778  long ds_obj_id = rs.getLong("obj_id");
2779  if (deviceIdToDatasourceObjIdMap.containsKey(deviceId)) {
2780  deviceIdToDatasourceObjIdMap.get(deviceId).add(ds_obj_id);
2781  } else {
2782  deviceIdToDatasourceObjIdMap.put(deviceId, new HashSet<Long>(Arrays.asList(ds_obj_id)));
2783  }
2784  }
2785  return dataSourceObjIds;
2786  } catch (SQLException ex) {
2787  throw new TskCoreException("Error getting data sources", ex);
2788  } finally {
2789  closeResultSet(rs);
2790  closeStatement(s);
2791  connection.close();
2793  }
2794  }
2795  }
2796 
2813  public List<DataSource> getDataSources() throws TskCoreException {
2814  CaseDbConnection connection = connections.getConnection();
2816  Statement statement = null;
2817  ResultSet resultSet = null;
2818  Statement statement2 = null;
2819  ResultSet resultSet2 = null;
2820  try {
2821  statement = connection.createStatement();
2822  statement2 = connection.createStatement();
2823  resultSet = connection.executeQuery(statement,
2824  "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 "
2825  + "FROM data_source_info AS ds "
2826  + "LEFT JOIN tsk_image_info AS img "
2827  + "ON ds.obj_id = img.obj_id"); //NON-NLS
2828 
2829  List<DataSource> dataSourceList = new ArrayList<DataSource>();
2830  Map<Long, List<String>> imagePathsMap = getImagePaths();
2831 
2832  while (resultSet.next()) {
2833  DataSource dataSource;
2834  Long objectId = resultSet.getLong("obj_id");
2835  String deviceId = resultSet.getString("device_id");
2836  String timezone = resultSet.getString("time_zone");
2837  String type = resultSet.getString("type");
2838 
2839  if (type == null) {
2840  /*
2841  * No data found in 'tsk_image_info', so we build a
2842  * LocalFilesDataSource.
2843  */
2844 
2845  resultSet2 = connection.executeQuery(statement2, "SELECT name FROM tsk_files WHERE tsk_files.obj_id = " + objectId); //NON-NLS
2846  String dsName = (resultSet2.next()) ? resultSet2.getString("name") : "";
2847  resultSet2.close();
2848 
2852  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
2853  | TSK_FS_META_FLAG_ENUM.USED.getValue());
2854  String parentPath = "/"; //NON-NLS
2855  dataSource = new LocalFilesDataSource(this, objectId, objectId, deviceId, dsName, dirType, metaType, dirFlag, metaFlags, timezone, null, null, FileKnown.UNKNOWN, parentPath);
2856  } else {
2857  /*
2858  * Data found in 'tsk_image_info', so we build an Image.
2859  */
2860  Long ssize = resultSet.getLong("ssize");
2861  Long size = resultSet.getLong("size");
2862  String md5 = resultSet.getString("md5");
2863  String sha1 = resultSet.getString("sha1");
2864  String sha256 = resultSet.getString("sha256");
2865  String name = resultSet.getString("display_name");
2866 
2867  List<String> imagePaths = imagePathsMap.get(objectId);
2868  if (name == null) {
2869  if (imagePaths.size() > 0) {
2870  String path = imagePaths.get(0);
2871  name = (new java.io.File(path)).getName();
2872  } else {
2873  name = "";
2874  }
2875  }
2876 
2877  dataSource = new Image(this, objectId, Long.valueOf(type), deviceId, ssize, name,
2878  imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
2879  }
2880 
2881  dataSourceList.add(dataSource);
2882  }
2883 
2884  return dataSourceList;
2885 
2886  } catch (SQLException ex) {
2887  throw new TskCoreException("Error getting data sources", ex);
2888  } finally {
2889  closeResultSet(resultSet);
2890  closeStatement(statement);
2891  closeResultSet(resultSet2);
2892  closeStatement(statement2);
2893  connection.close();
2895  }
2896  }
2897 
2917  public DataSource getDataSource(long objectId) throws TskDataException, TskCoreException {
2918  DataSource dataSource = null;
2919  CaseDbConnection connection = connections.getConnection();
2921  Statement statement = null;
2922  ResultSet resultSet = null;
2923  Statement statement2 = null;
2924  ResultSet resultSet2 = null;
2925  try {
2926  statement = connection.createStatement();
2927  statement2 = connection.createStatement();
2928  resultSet = connection.executeQuery(statement,
2929  "SELECT ds.device_id, ds.time_zone, img.type, img.ssize, img.size, img.md5, img.sha1, img.sha256, img.display_name "
2930  + "FROM data_source_info AS ds "
2931  + "LEFT JOIN tsk_image_info AS img "
2932  + "ON ds.obj_id = img.obj_id "
2933  + "WHERE ds.obj_id = " + objectId); //NON-NLS
2934  if (resultSet.next()) {
2935  String deviceId = resultSet.getString("device_id");
2936  String timezone = resultSet.getString("time_zone");
2937  String type = resultSet.getString("type");
2938 
2939  if (type == null) {
2940  /*
2941  * No data found in 'tsk_image_info', so we build an
2942  * LocalFilesDataSource.
2943  */
2944 
2945  resultSet2 = connection.executeQuery(statement2, "SELECT name FROM tsk_files WHERE tsk_files.obj_id = " + objectId); //NON-NLS
2946  String dsName = (resultSet2.next()) ? resultSet2.getString("name") : "";
2947 
2951  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
2952  | TSK_FS_META_FLAG_ENUM.USED.getValue());
2953  String parentPath = "/"; //NON-NLS
2954  dataSource = new LocalFilesDataSource(this, objectId, objectId, deviceId, dsName, dirType, metaType, dirFlag, metaFlags, timezone, null, null, FileKnown.UNKNOWN, parentPath);
2955  } else {
2956  /*
2957  * Data found in 'tsk_image_info', so we build an Image.
2958  */
2959  Long ssize = resultSet.getLong("ssize");
2960  Long size = resultSet.getLong("size");
2961  String md5 = resultSet.getString("md5");
2962  String sha1 = resultSet.getString("sha1");
2963  String sha256 = resultSet.getString("sha256");
2964  String name = resultSet.getString("display_name");
2965 
2966  List<String> imagePaths = getImagePathsById(objectId);
2967  if (name == null) {
2968  if (imagePaths.size() > 0) {
2969  String path = imagePaths.get(0);
2970  name = (new java.io.File(path)).getName();
2971  } else {
2972  name = "";
2973  }
2974  }
2975 
2976  dataSource = new Image(this, objectId, Long.valueOf(type), deviceId, ssize, name,
2977  imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
2978  }
2979  } else {
2980  throw new TskDataException(String.format("There is no data source with obj_id = %d", objectId));
2981  }
2982  } catch (SQLException ex) {
2983  throw new TskCoreException(String.format("Error getting data source with obj_id = %d", objectId), ex);
2984  } finally {
2985  closeResultSet(resultSet);
2986  closeStatement(statement);
2987  closeResultSet(resultSet2);
2988  closeStatement(statement2);
2989  connection.close();
2991  }
2992 
2993  return dataSource;
2994  }
2995 
3006  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(int artifactTypeID) throws TskCoreException {
3007  return getArtifactsHelper("blackboard_artifacts.artifact_type_id = " + artifactTypeID);
3008  }
3009 
3020  public long getBlackboardArtifactsCount(long objId) throws TskCoreException {
3021  CaseDbConnection connection = connections.getConnection();
3023  ResultSet rs = null;
3024  try {
3025  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ?
3026  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_FROM_SOURCE);
3027  statement.clearParameters();
3028  statement.setLong(1, objId);
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 content", ex);
3037  } finally {
3038  closeResultSet(rs);
3039  connection.close();
3041  }
3042  }
3043 
3054  public long getBlackboardArtifactsTypeCount(int artifactTypeID) throws TskCoreException {
3055  CaseDbConnection connection = connections.getConnection();
3057  ResultSet rs = null;
3058  try {
3059  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ?
3060  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_OF_TYPE);
3061  statement.clearParameters();
3062  statement.setInt(1, artifactTypeID);
3063  rs = connection.executeQuery(statement);
3064  long count = 0;
3065  if (rs.next()) {
3066  count = rs.getLong("count");
3067  }
3068  return count;
3069  } catch (SQLException ex) {
3070  throw new TskCoreException("Error getting number of blackboard artifacts by type", ex);
3071  } finally {
3072  closeResultSet(rs);
3073  connection.close();
3075  }
3076  }
3077 
3089  public long getBlackboardArtifactsTypeCount(int artifactTypeID, long dataSourceID) throws TskCoreException {
3090  CaseDbConnection connection = connections.getConnection();
3092  ResultSet rs = null;
3093  try {
3094  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ?
3095  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_OF_TYPE_BY_DATA_SOURCE);
3096  statement.clearParameters();
3097  statement.setInt(2, artifactTypeID);
3098  statement.setLong(1, dataSourceID);
3099  rs = connection.executeQuery(statement);
3100  long count = 0;
3101  if (rs.next()) {
3102  count = rs.getLong("count");
3103  }
3104  return count;
3105  } catch (SQLException ex) {
3106  throw new TskCoreException(String.format("Error getting number of blackboard artifacts by type (%d) and data source (%d)", artifactTypeID, dataSourceID), ex);
3107  } finally {
3108  closeResultSet(rs);
3109  connection.close();
3111  }
3112  }
3113 
3128  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value) throws TskCoreException {
3129  CaseDbConnection connection = connections.getConnection();
3131  Statement s = null;
3132  ResultSet rs = null;
3133  try {
3134  s = connection.createStatement();
3135  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3136  + "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, "
3137  + "types.type_name AS type_name, types.display_name AS display_name, "//NON-NLS
3138  + " arts.review_status_id AS review_status_id " //NON-NLS
3139  + "FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3140  + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3141  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3142  + " AND attrs.value_text = '" + value + "'"
3143  + " AND types.artifact_type_id=arts.artifact_type_id"
3144  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()); //NON-NLS
3145  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3146  while (rs.next()) {
3147  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3148  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3149  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3150  }
3151  return artifacts;
3152  } catch (SQLException ex) {
3153  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3154  } finally {
3155  closeResultSet(rs);
3156  closeStatement(s);
3157  connection.close();
3159  }
3160  }
3161 
3179  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String subString, boolean startsWith) throws TskCoreException {
3180  String valSubStr = "%" + subString; //NON-NLS
3181  if (startsWith == false) {
3182  valSubStr += "%"; //NON-NLS
3183  }
3184  CaseDbConnection connection = connections.getConnection();
3186  Statement s = null;
3187  ResultSet rs = null;
3188  try {
3189  s = connection.createStatement();
3190  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3191  + " 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
3192  + " types.type_name AS type_name, types.display_name AS display_name, " //NON-NLS
3193  + " arts.review_status_id AS review_status_id " //NON-NLS
3194  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3195  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3196  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3197  + " AND LOWER(attrs.value_text) LIKE LOWER('" + valSubStr + "')"
3198  + " AND types.artifact_type_id=arts.artifact_type_id "
3199  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3200  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3201  while (rs.next()) {
3202  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3203  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3204  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3205  }
3206  return artifacts;
3207  } catch (SQLException ex) {
3208  throw new TskCoreException("Error getting blackboard artifacts by attribute. " + ex.getMessage(), ex);
3209  } finally {
3210  closeResultSet(rs);
3211  closeStatement(s);
3212  connection.close();
3214  }
3215  }
3216 
3231  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, int value) throws TskCoreException {
3232  CaseDbConnection connection = connections.getConnection();
3234  Statement s = null;
3235  ResultSet rs = null;
3236  try {
3237  s = connection.createStatement();
3238  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3239  + " 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, "
3240  + " types.type_name AS type_name, types.display_name AS display_name, "
3241  + " arts.review_status_id AS review_status_id "//NON-NLS
3242  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3243  + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3244  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3245  + " AND attrs.value_int32 = " + value //NON-NLS
3246  + " AND types.artifact_type_id=arts.artifact_type_id "
3247  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3248  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3249  while (rs.next()) {
3250  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3251  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3252  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3253  }
3254  return artifacts;
3255  } catch (SQLException ex) {
3256  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3257  } finally {
3258  closeResultSet(rs);
3259  closeStatement(s);
3260  connection.close();
3262  }
3263  }
3264 
3279  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, long value) throws TskCoreException {
3280  CaseDbConnection connection = connections.getConnection();
3282  Statement s = null;
3283  ResultSet rs = null;
3284  try {
3285  s = connection.createStatement();
3286  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3287  + " 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, "
3288  + " types.type_name AS type_name, types.display_name AS display_name, "
3289  + " arts.review_status_id AS review_status_id "//NON-NLS
3290  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3291  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3292  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3293  + " AND attrs.value_int64 = " + value //NON-NLS
3294  + " AND types.artifact_type_id=arts.artifact_type_id "
3295  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3296  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3297  while (rs.next()) {
3298  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3299  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3300  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3301  }
3302  return artifacts;
3303  } catch (SQLException ex) {
3304  throw new TskCoreException("Error getting blackboard artifacts by attribute. " + ex.getMessage(), ex);
3305  } finally {
3306  closeResultSet(rs);
3307  closeStatement(s);
3308  connection.close();
3310  }
3311  }
3312 
3327  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, double value) throws TskCoreException {
3328  CaseDbConnection connection = connections.getConnection();
3330  Statement s = null;
3331  ResultSet rs = null;
3332  try {
3333  s = connection.createStatement();
3334  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3335  + " 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, "
3336  + " types.type_name AS type_name, types.display_name AS display_name, "
3337  + " arts.review_status_id AS review_status_id "//NON-NLS
3338  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3339  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3340  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3341  + " AND attrs.value_double = " + value //NON-NLS
3342  + " AND types.artifact_type_id=arts.artifact_type_id "
3343  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3344  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3345  while (rs.next()) {
3346  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3347  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3348  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3349  }
3350  return artifacts;
3351  } catch (SQLException ex) {
3352  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3353  } finally {
3354  closeResultSet(rs);
3355  closeStatement(s);
3356  connection.close();
3358  }
3359  }
3360 
3375  public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, byte value) throws TskCoreException {
3376  CaseDbConnection connection = connections.getConnection();
3378  Statement s = null;
3379  ResultSet rs = null;
3380  try {
3381  s = connection.createStatement();
3382  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3383  + " 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, "
3384  + " types.type_name AS type_name, types.display_name AS display_name, "
3385  + " arts.review_status_id AS review_status_id "//NON-NLS
3386  + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3387  + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3388  + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3389  + " AND attrs.value_byte = " + value //NON-NLS
3390  + " AND types.artifact_type_id=arts.artifact_type_id "
3391  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3392  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3393  while (rs.next()) {
3394  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3395  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3396  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3397  }
3398  return artifacts;
3399  } catch (SQLException ex) {
3400  throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
3401  } finally {
3402  closeResultSet(rs);
3403  closeStatement(s);
3404  connection.close();
3406  }
3407  }
3408 
3416  public Iterable<BlackboardArtifact.Type> getArtifactTypes() throws TskCoreException {
3417  CaseDbConnection connection = connections.getConnection();
3419  Statement s = null;
3420  ResultSet rs = null;
3421  try {
3422  s = connection.createStatement();
3423  rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name FROM blackboard_artifact_types"); //NON-NLS
3424  ArrayList<BlackboardArtifact.Type> artifactTypes = new ArrayList<BlackboardArtifact.Type>();
3425  while (rs.next()) {
3426  artifactTypes.add(new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
3427  rs.getString("type_name"), rs.getString("display_name")));
3428  }
3429  return artifactTypes;
3430  } catch (SQLException ex) {
3431  throw new TskCoreException("Error getting artifact types", ex); //NON-NLS
3432  } finally {
3433  closeResultSet(rs);
3434  closeStatement(s);
3435  connection.close();
3437  }
3438  }
3439 
3448  public ArrayList<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardArtifactTypesInUse() throws TskCoreException {
3449  String typeIdList = "";
3450  for (int i = 0; i < BlackboardArtifact.ARTIFACT_TYPE.values().length; ++i) {
3451  typeIdList += BlackboardArtifact.ARTIFACT_TYPE.values()[i].getTypeID();
3452  if (i < BlackboardArtifact.ARTIFACT_TYPE.values().length - 1) {
3453  typeIdList += ", ";
3454  }
3455  }
3456  String query = "SELECT DISTINCT artifact_type_id FROM blackboard_artifacts "
3457  + "WHERE artifact_type_id IN (" + typeIdList + ")";
3458  CaseDbConnection connection = connections.getConnection();
3460  Statement s = null;
3461  ResultSet rs = null;
3462  try {
3463  s = connection.createStatement();
3464  rs = connection.executeQuery(s, query);
3465  ArrayList<BlackboardArtifact.ARTIFACT_TYPE> usedArts = new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>();
3466  while (rs.next()) {
3467  usedArts.add(ARTIFACT_TYPE.fromID(rs.getInt("artifact_type_id")));
3468  }
3469  return usedArts;
3470  } catch (SQLException ex) {
3471  throw new TskCoreException("Error getting artifact types in use", ex);
3472  } finally {
3473  closeResultSet(rs);
3474  closeStatement(s);
3475  connection.close();
3477  }
3478  }
3479 
3490  public List<BlackboardArtifact.Type> getArtifactTypesInUse() throws TskCoreException {
3491  CaseDbConnection connection = connections.getConnection();
3493  Statement s = null;
3494  ResultSet rs = null;
3495  try {
3496  s = connection.createStatement();
3497  rs = connection.executeQuery(s,
3498  "SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, "
3499  + "types.type_name AS type_name, types.display_name AS display_name "
3500  + "FROM blackboard_artifact_types AS types "
3501  + "INNER JOIN blackboard_artifacts AS arts "
3502  + "ON arts.artifact_type_id = types.artifact_type_id"); //NON-NLS
3503  List<BlackboardArtifact.Type> uniqueArtifactTypes = new ArrayList<BlackboardArtifact.Type>();
3504  while (rs.next()) {
3505  uniqueArtifactTypes.add(new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
3506  rs.getString("type_name"), rs.getString("display_name")));
3507  }
3508  return uniqueArtifactTypes;
3509  } catch (SQLException ex) {
3510  throw new TskCoreException("Error getting attribute types", ex);
3511  } finally {
3512  closeResultSet(rs);
3513  closeStatement(s);
3514  connection.close();
3516  }
3517  }
3518 
3526  public List<BlackboardAttribute.Type> getAttributeTypes() throws TskCoreException {
3527  CaseDbConnection connection = connections.getConnection();
3529  Statement s = null;
3530  ResultSet rs = null;
3531  try {
3532  s = connection.createStatement();
3533  rs = connection.executeQuery(s, "SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types"); //NON-NLS
3534  ArrayList<BlackboardAttribute.Type> attribute_types = new ArrayList<BlackboardAttribute.Type>();
3535  while (rs.next()) {
3536  attribute_types.add(new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
3537  rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type"))));
3538  }
3539  return attribute_types;
3540  } catch (SQLException ex) {
3541  throw new TskCoreException("Error getting attribute types", ex);
3542  } finally {
3543  closeResultSet(rs);
3544  closeStatement(s);
3545  connection.close();
3547  }
3548  }
3549 
3561  public int getBlackboardAttributeTypesCount() throws TskCoreException {
3562  CaseDbConnection connection = connections.getConnection();
3564  Statement s = null;
3565  ResultSet rs = null;
3566  try {
3567  s = connection.createStatement();
3568  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM blackboard_attribute_types"); //NON-NLS
3569  int count = 0;
3570  if (rs.next()) {
3571  count = rs.getInt("count");
3572  }
3573  return count;
3574  } catch (SQLException ex) {
3575  throw new TskCoreException("Error getting number of blackboard artifacts by type", ex);
3576  } finally {
3577  closeResultSet(rs);
3578  closeStatement(s);
3579  connection.close();
3581  }
3582  }
3583 
3596  ArrayList<BlackboardArtifact> getArtifactsHelper(String whereClause) throws TskCoreException {
3597  CaseDbConnection connection = connections.getConnection();
3599  ResultSet rs = null;
3600  try {
3601  Statement statement = connection.createStatement();
3602  String query = "SELECT blackboard_artifacts.artifact_id AS artifact_id, "
3603  + "blackboard_artifacts.obj_id AS obj_id, "
3604  + "blackboard_artifacts.artifact_obj_id AS artifact_obj_id, "
3605  + "blackboard_artifacts.data_source_obj_id AS data_source_obj_id, "
3606  + "blackboard_artifact_types.artifact_type_id AS artifact_type_id, "
3607  + "blackboard_artifact_types.type_name AS type_name, "
3608  + "blackboard_artifact_types.display_name AS display_name, "
3609  + "blackboard_artifacts.review_status_id AS review_status_id "
3610  + "FROM blackboard_artifacts, blackboard_artifact_types "
3611  + "WHERE blackboard_artifacts.artifact_type_id = blackboard_artifact_types.artifact_type_id "
3612  + " AND blackboard_artifacts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID()
3613  + " AND " + whereClause;
3614  rs = connection.executeQuery(statement, query);
3615  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3616  while (rs.next()) {
3617  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3618  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3619  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3620  }
3621  return artifacts;
3622  } catch (SQLException ex) {
3623  throw new TskCoreException("Error getting or creating a blackboard artifact", ex);
3624  } finally {
3625  closeResultSet(rs);
3626  connection.close();
3628  }
3629  }
3630 
3643  private long getArtifactsCountHelper(int artifactTypeID, long obj_id) throws TskCoreException {
3644  CaseDbConnection connection = connections.getConnection();
3646  ResultSet rs = null;
3647  try {
3648  // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND artifact_type_id = ?
3649  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_SOURCE_AND_TYPE);
3650  statement.clearParameters();
3651  statement.setLong(1, obj_id);
3652  statement.setInt(2, artifactTypeID);
3653  rs = connection.executeQuery(statement);
3654  long count = 0;
3655  if (rs.next()) {
3656  count = rs.getLong("count");
3657  }
3658  return count;
3659  } catch (SQLException ex) {
3660  throw new TskCoreException("Error getting blackboard artifact count", ex);
3661  } finally {
3662  closeResultSet(rs);
3663  connection.close();
3665  }
3666  }
3667 
3680  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(String artifactTypeName, long obj_id) throws TskCoreException {
3681  return getArtifactsHelper("blackboard_artifacts.obj_id = " + obj_id + " AND blackboard_artifact_types.type_name = '" + artifactTypeName + "';");
3682  }
3683 
3696  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(int artifactTypeID, long obj_id) throws TskCoreException {
3697  return getArtifactsHelper("blackboard_artifacts.obj_id = " + obj_id + " AND blackboard_artifact_types.artifact_type_id = " + artifactTypeID + ";");
3698  }
3699 
3712  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
3713  return getBlackboardArtifacts(artifactType.getTypeID(), obj_id);
3714  }
3715 
3728  public long getBlackboardArtifactsCount(String artifactTypeName, long obj_id) throws TskCoreException {
3729  int artifactTypeID = this.getArtifactType(artifactTypeName).getTypeID();
3730  if (artifactTypeID == -1) {
3731  return 0;
3732  }
3733  return getArtifactsCountHelper(artifactTypeID, obj_id);
3734  }
3735 
3748  public long getBlackboardArtifactsCount(int artifactTypeID, long obj_id) throws TskCoreException {
3749  return getArtifactsCountHelper(artifactTypeID, obj_id);
3750  }
3751 
3764  public long getBlackboardArtifactsCount(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
3765  return getArtifactsCountHelper(artifactType.getTypeID(), obj_id);
3766  }
3767 
3779  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(String artifactTypeName) throws TskCoreException {
3780  return getArtifactsHelper("blackboard_artifact_types.type_name = '" + artifactTypeName + "';");
3781  }
3782 
3794  public ArrayList<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType) throws TskCoreException {
3795  return getArtifactsHelper("blackboard_artifact_types.artifact_type_id = " + artifactType.getTypeID() + ";");
3796  }
3797 
3811  public List<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value) throws TskCoreException {
3812  CaseDbConnection connection = connections.getConnection();
3814  Statement s = null;
3815  ResultSet rs = null;
3816  try {
3817  s = connection.createStatement();
3818  rs = connection.executeQuery(s, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
3819  + "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, "
3820  + "types.type_name AS type_name, types.display_name AS display_name,"
3821  + "arts.review_status_id AS review_status_id "//NON-NLS
3822  + "FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
3823  + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
3824  + "AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
3825  + " AND arts.artifact_type_id = " + artifactType.getTypeID() //NON-NLS
3826  + " AND attrs.value_text = '" + value + "'" //NON-NLS
3827  + " AND types.artifact_type_id=arts.artifact_type_id"
3828  + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());
3829  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
3830  while (rs.next()) {
3831  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3832  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3833  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
3834  }
3835  return artifacts;
3836  } catch (SQLException ex) {
3837  throw new TskCoreException("Error getting blackboard artifacts by artifact type and attribute. " + ex.getMessage(), ex);
3838  } finally {
3839  closeResultSet(rs);
3840  closeStatement(s);
3841  connection.close();
3843  }
3844  }
3845 
3856  public BlackboardArtifact getBlackboardArtifact(long artifactID) throws TskCoreException {
3857  CaseDbConnection connection = connections.getConnection();
3859  ResultSet rs = null;
3860  Statement s;
3861  try {
3862  s = connection.createStatement();
3863  rs = connection.executeQuery(s, "SELECT arts.artifact_id AS artifact_id, "
3864  + "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, "
3865  + "types.type_name AS type_name, types.display_name AS display_name,"
3866  + "arts.review_status_id AS review_status_id "//NON-NLS
3867  + "FROM blackboard_artifacts AS arts, blackboard_artifact_types AS types "
3868  + "WHERE arts.artifact_id = " + artifactID
3869  + " AND arts.artifact_type_id = types.artifact_type_id");
3870  if (rs.next()) {
3871  return new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
3872  rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
3873  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")));
3874  } else {
3875  /*
3876  * I think this should actually return null (or Optional) when
3877  * there is no artifact with the given id, but it looks like
3878  * existing code is not expecting that. -jm
3879  */
3880  throw new TskCoreException("No blackboard artifact with id " + artifactID);
3881  }
3882  } catch (SQLException ex) {
3883  throw new TskCoreException("Error getting a blackboard artifact. " + ex.getMessage(), ex);
3884  } finally {
3885  closeResultSet(rs);
3886  connection.close();
3888  }
3889  }
3890 
3899  public void addBlackboardAttribute(BlackboardAttribute attr, int artifactTypeId) throws TskCoreException {
3900  CaseDbConnection connection = connections.getConnection();
3902  try {
3903  addBlackBoardAttribute(attr, artifactTypeId, connection);
3904  } catch (SQLException ex) {
3905  throw new TskCoreException("Error adding blackboard attribute " + attr.toString(), ex);
3906  } finally {
3907  connection.close();
3909  }
3910  }
3911 
3921  public void addBlackboardAttributes(Collection<BlackboardAttribute> attributes, int artifactTypeId) throws TskCoreException {
3922  CaseDbConnection connection = connections.getConnection();
3924  try {
3925  connection.beginTransaction();
3926  for (final BlackboardAttribute attr : attributes) {
3927  addBlackBoardAttribute(attr, artifactTypeId, connection);
3928  }
3929  connection.commitTransaction();
3930  } catch (SQLException ex) {
3931  connection.rollbackTransaction();
3932  throw new TskCoreException("Error adding blackboard attributes", ex);
3933  } finally {
3934  connection.close();
3936  }
3937  }
3938 
3939  private void addBlackBoardAttribute(BlackboardAttribute attr, int artifactTypeId, CaseDbConnection connection) throws SQLException, TskCoreException {
3940  PreparedStatement statement;
3941  switch (attr.getAttributeType().getValueType()) {
3942  case STRING:
3943  case JSON:
3944  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_STRING_ATTRIBUTE);
3945  statement.clearParameters();
3946  statement.setString(7, attr.getValueString());
3947  break;
3948  case BYTE:
3949  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_BYTE_ATTRIBUTE);
3950  statement.clearParameters();
3951  statement.setBytes(7, attr.getValueBytes());
3952  break;
3953  case INTEGER:
3954  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INT_ATTRIBUTE);
3955  statement.clearParameters();
3956  statement.setInt(7, attr.getValueInt());
3957  break;
3958  case LONG:
3959  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LONG_ATTRIBUTE);
3960  statement.clearParameters();
3961  statement.setLong(7, attr.getValueLong());
3962  break;
3963  case DOUBLE:
3964  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DOUBLE_ATTRIBUTE);
3965  statement.clearParameters();
3966  statement.setDouble(7, attr.getValueDouble());
3967  break;
3968  case DATETIME:
3969  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LONG_ATTRIBUTE);
3970  statement.clearParameters();
3971  statement.setLong(7, attr.getValueLong());
3972  break;
3973  default:
3974  throw new TskCoreException("Unrecognized artifact attribute value type");
3975  }
3976  statement.setLong(1, attr.getArtifactID());
3977  statement.setInt(2, artifactTypeId);
3978  statement.setString(3, attr.getSourcesCSV());
3979  statement.setString(4, "");
3980  statement.setInt(5, attr.getAttributeType().getTypeID());
3981  statement.setLong(6, attr.getAttributeType().getValueType().getType());
3982  connection.executeUpdate(statement);
3983  }
3984 
3995  String addSourceToArtifactAttribute(BlackboardAttribute attr, String source) throws TskCoreException {
3996  /*
3997  * WARNING: This is a temporary implementation that is not safe and
3998  * denormalizes the case datbase.
3999  *
4000  * TODO (JIRA-2294): Provide a safe and normalized solution to tracking
4001  * the sources of artifact attributes.
4002  */
4003  if (null == source || source.isEmpty()) {
4004  throw new TskCoreException("Attempt to add null or empty source module name to artifact attribute");
4005  }
4006  CaseDbConnection connection = connections.getConnection();
4008  Statement queryStmt = null;
4009  Statement updateStmt = null;
4010  ResultSet result = null;
4011  String newSources = "";
4012  try {
4013  connection.beginTransaction();
4014  String valueClause = "";
4015  BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType = attr.getAttributeType().getValueType();
4016  if (BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE != valueType) {
4017  switch (valueType) {
4018  case STRING:
4019  case JSON:
4020  valueClause = " value_text = '" + escapeSingleQuotes(attr.getValueString()) + "'";
4021  break;
4022  case INTEGER:
4023  valueClause = " value_int32 = " + attr.getValueInt();
4024  break;
4025  case LONG:
4026  case DATETIME:
4027  valueClause = " value_int64 = " + attr.getValueLong();
4028  break;
4029  case DOUBLE:
4030  valueClause = " value_double = " + attr.getValueDouble();
4031  break;
4032  default:
4033  throw new TskCoreException(String.format("Unrecognized value type for attribute %s", attr.getDisplayString()));
4034  }
4035  String query = "SELECT source FROM blackboard_attributes 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  queryStmt = connection.createStatement();
4041  updateStmt = connection.createStatement();
4042  result = connection.executeQuery(queryStmt, query);
4043  } else {
4044  /*
4045  * SELECT source FROM blackboard_attributes WHERE artifact_id =
4046  * ? AND attribute_type_id = ? AND value_type = 4 AND value_byte
4047  * = ?
4048  */
4049  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ATTR_BY_VALUE_BYTE);
4050  statement.clearParameters();
4051  statement.setLong(1, attr.getArtifactID());
4052  statement.setLong(2, attr.getAttributeType().getTypeID());
4053  statement.setBytes(3, attr.getValueBytes());
4054  result = connection.executeQuery(statement);
4055  }
4056  while (result.next()) {
4057  String oldSources = result.getString("source");
4058  if (null != oldSources && !oldSources.isEmpty()) {
4059  Set<String> uniqueSources = new HashSet<String>(Arrays.asList(oldSources.split(",")));
4060  if (!uniqueSources.contains(source)) {
4061  newSources = oldSources + "," + source;
4062  } else {
4063  newSources = oldSources;
4064  }
4065  } else {
4066  newSources = source;
4067  }
4068  if (BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE != valueType) {
4069  String update = "UPDATE blackboard_attributes SET source = '" + newSources + "' WHERE"
4070  + " artifact_id = " + attr.getArtifactID()
4071  + " AND attribute_type_id = " + attr.getAttributeType().getTypeID()
4072  + " AND value_type = " + attr.getAttributeType().getValueType().getType()
4073  + " AND " + valueClause + ";";
4074  connection.executeUpdate(updateStmt, update);
4075  } else {
4076  /*
4077  * UPDATE blackboard_attributes SET source = ? WHERE
4078  * artifact_id = ? AND attribute_type_id = ? AND value_type
4079  * = 4 AND value_byte = ?
4080  */
4081  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ATTR_BY_VALUE_BYTE);
4082  statement.clearParameters();
4083  statement.setString(1, newSources);
4084  statement.setLong(2, attr.getArtifactID());
4085  statement.setLong(3, attr.getAttributeType().getTypeID());
4086  statement.setBytes(4, attr.getValueBytes());
4087  connection.executeUpdate(statement);
4088  }
4089  }
4090  connection.commitTransaction();
4091  return newSources;
4092  } catch (SQLException ex) {
4093  connection.rollbackTransaction();
4094  throw new TskCoreException(String.format("Error adding source module to attribute %s", attr.getDisplayString()), ex);
4095  } finally {
4096  closeResultSet(result);
4097  closeStatement(updateStmt);
4098  closeStatement(queryStmt);
4099  connection.close();
4101  }
4102  }
4103 
4118  public BlackboardAttribute.Type addArtifactAttributeType(String attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName) throws TskCoreException, TskDataException {
4119  CaseDbConnection connection = connections.getConnection();
4121  Statement s = null;
4122  ResultSet rs = null;
4123  try {
4124  connection.beginTransaction();
4125  s = connection.createStatement();
4126  rs = connection.executeQuery(s, "SELECT attribute_type_id FROM blackboard_attribute_types WHERE type_name = '" + attrTypeString + "'"); //NON-NLS
4127  if (!rs.next()) {
4128  rs.close();
4129  rs = connection.executeQuery(s, "SELECT MAX(attribute_type_id) AS highest_id FROM blackboard_attribute_types");
4130  int maxID = 0;
4131  if (rs.next()) {
4132  maxID = rs.getInt("highest_id");
4133  if (maxID < MIN_USER_DEFINED_TYPE_ID) {
4134  maxID = MIN_USER_DEFINED_TYPE_ID;
4135  } else {
4136  maxID++;
4137  }
4138  }
4139  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
4140  BlackboardAttribute.Type type = new BlackboardAttribute.Type(maxID, attrTypeString, displayName, valueType);
4141  this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
4142  this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
4143  connection.commitTransaction();
4144  return type;
4145  } else {
4146  throw new TskDataException("The attribute type that was added was already within the system.");
4147  }
4148 
4149  } catch (SQLException ex) {
4150  connection.rollbackTransaction();
4151  throw new TskCoreException("Error adding attribute type", ex);
4152  } finally {
4153  closeResultSet(rs);
4154  closeStatement(s);
4155  connection.close();
4157  }
4158  }
4159 
4170  public BlackboardAttribute.Type getAttributeType(String attrTypeName) throws TskCoreException {
4171  if (this.typeNameToAttributeTypeMap.containsKey(attrTypeName)) {
4172  return this.typeNameToAttributeTypeMap.get(attrTypeName);
4173  }
4174  CaseDbConnection connection = connections.getConnection();
4176  Statement s = null;
4177  ResultSet rs = null;
4178  try {
4179  s = connection.createStatement();
4180  rs = connection.executeQuery(s, "SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName + "'"); //NON-NLS
4181  BlackboardAttribute.Type type = null;
4182  if (rs.next()) {
4183  type = new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
4184  rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type")));
4185  this.typeIdToAttributeTypeMap.put(type.getTypeID(), type);
4186  this.typeNameToAttributeTypeMap.put(attrTypeName, type);
4187  }
4188  return type;
4189  } catch (SQLException ex) {
4190  throw new TskCoreException("Error getting attribute type id", ex);
4191  } finally {
4192  closeResultSet(rs);
4193  closeStatement(s);
4194  connection.close();
4196  }
4197  }
4198 
4209  private BlackboardAttribute.Type getAttributeType(int typeID) throws TskCoreException {
4210  if (this.typeIdToAttributeTypeMap.containsKey(typeID)) {
4211  return this.typeIdToAttributeTypeMap.get(typeID);
4212  }
4213  CaseDbConnection connection = connections.getConnection();
4215  Statement s = null;
4216  ResultSet rs = null;
4217  try {
4218  s = connection.createStatement();
4219  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
4220  BlackboardAttribute.Type type = null;
4221  if (rs.next()) {
4222  type = new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
4223  rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type")));
4224  this.typeIdToAttributeTypeMap.put(typeID, type);
4225  this.typeNameToAttributeTypeMap.put(type.getTypeName(), type);
4226  }
4227  return type;
4228  } catch (SQLException ex) {
4229  throw new TskCoreException("Error getting attribute type id", ex);
4230  } finally {
4231  closeResultSet(rs);
4232  closeStatement(s);
4233  connection.close();
4235  }
4236  }
4237 
4248  public BlackboardArtifact.Type getArtifactType(String artTypeName) throws TskCoreException {
4249  if (this.typeNameToArtifactTypeMap.containsKey(artTypeName)) {
4250  return this.typeNameToArtifactTypeMap.get(artTypeName);
4251  }
4252  CaseDbConnection connection = connections.getConnection();
4254  Statement s = null;
4255  ResultSet rs = null;
4256  try {
4257  s = connection.createStatement();
4258  rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name FROM blackboard_artifact_types WHERE type_name = '" + artTypeName + "'"); //NON-NLS
4259  BlackboardArtifact.Type type = null;
4260  if (rs.next()) {
4261  type = new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
4262  rs.getString("type_name"), rs.getString("display_name"));
4263  this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
4264  this.typeNameToArtifactTypeMap.put(artTypeName, type);
4265  }
4266  return type;
4267  } catch (SQLException ex) {
4268  throw new TskCoreException("Error getting artifact type from the database", ex);
4269  } finally {
4270  closeResultSet(rs);
4271  closeStatement(s);
4272  connection.close();
4274  }
4275  }
4276 
4287  BlackboardArtifact.Type getArtifactType(int artTypeId) throws TskCoreException {
4288  if (this.typeIdToArtifactTypeMap.containsKey(artTypeId)) {
4289  return typeIdToArtifactTypeMap.get(artTypeId);
4290  }
4291  CaseDbConnection connection = connections.getConnection();
4293  Statement s = null;
4294  ResultSet rs = null;
4295  try {
4296  s = connection.createStatement();
4297  rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name FROM blackboard_artifact_types WHERE artifact_type_id = " + artTypeId + ""); //NON-NLS
4298  BlackboardArtifact.Type type = null;
4299  if (rs.next()) {
4300  type = new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
4301  rs.getString("type_name"), rs.getString("display_name"));
4302  this.typeIdToArtifactTypeMap.put(artTypeId, type);
4303  this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
4304  }
4305  return type;
4306  } catch (SQLException ex) {
4307  throw new TskCoreException("Error getting artifact type from the database", ex);
4308  } finally {
4309  closeResultSet(rs);
4310  closeStatement(s);
4311  connection.close();
4313  }
4314  }
4315 
4328  public BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName) throws TskCoreException, TskDataException {
4329  CaseDbConnection connection = connections.getConnection();
4331  Statement s = null;
4332  ResultSet rs = null;
4333  try {
4334  connection.beginTransaction();
4335  s = connection.createStatement();
4336  rs = connection.executeQuery(s, "SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = '" + artifactTypeName + "'"); //NON-NLS
4337  if (!rs.next()) {
4338  rs.close();
4339  rs = connection.executeQuery(s, "SELECT MAX(artifact_type_id) AS highest_id FROM blackboard_artifact_types");
4340  int maxID = 0;
4341  if (rs.next()) {
4342  maxID = rs.getInt("highest_id");
4343  if (maxID < MIN_USER_DEFINED_TYPE_ID) {
4344  maxID = MIN_USER_DEFINED_TYPE_ID;
4345  } else {
4346  maxID++;
4347  }
4348  }
4349  connection.executeUpdate(s, "INSERT INTO blackboard_artifact_types (artifact_type_id, type_name, display_name) VALUES ('" + maxID + "', '" + artifactTypeName + "', '" + displayName + "')"); //NON-NLS
4350  BlackboardArtifact.Type type = new BlackboardArtifact.Type(maxID, artifactTypeName, displayName);
4351  this.typeIdToArtifactTypeMap.put(type.getTypeID(), type);
4352  this.typeNameToArtifactTypeMap.put(type.getTypeName(), type);
4353  connection.commitTransaction();
4354  return type;
4355  } else {
4356  throw new TskDataException("The attribute type that was added was already within the system.");
4357  }
4358  } catch (SQLException ex) {
4359  connection.rollbackTransaction();
4360  throw new TskCoreException("Error adding artifact type", ex);
4361  } finally {
4362  closeResultSet(rs);
4363  closeStatement(s);
4364  connection.close();
4366  }
4367  }
4368 
4369  public ArrayList<BlackboardAttribute> getBlackboardAttributes(final BlackboardArtifact artifact) throws TskCoreException {
4370  CaseDbConnection connection = connections.getConnection();
4372  ResultSet rs = null;
4373  try {
4374  Statement statement = connection.createStatement();
4375  rs = connection.executeQuery(statement, "SELECT attrs.artifact_id AS artifact_id, "
4376  + "attrs.source AS source, attrs.context AS context, attrs.attribute_type_id AS attribute_type_id, "
4377  + "attrs.value_type AS value_type, attrs.value_byte AS value_byte, "
4378  + "attrs.value_text AS value_text, attrs.value_int32 AS value_int32, "
4379  + "attrs.value_int64 AS value_int64, attrs.value_double AS value_double, "
4380  + "types.type_name AS type_name, types.display_name AS display_name "
4381  + "FROM blackboard_attributes AS attrs, blackboard_attribute_types AS types WHERE attrs.artifact_id = " + artifact.getArtifactID()
4382  + " AND attrs.attribute_type_id = types.attribute_type_id");
4383  ArrayList<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
4384  while (rs.next()) {
4385  int attributeTypeId = rs.getInt("attribute_type_id");
4386  String attributeTypeName = rs.getString("type_name");
4387  BlackboardAttribute.Type attributeType;
4388  if (this.typeIdToAttributeTypeMap.containsKey(attributeTypeId)) {
4389  attributeType = this.typeIdToAttributeTypeMap.get(attributeTypeId);
4390  } else {
4391  attributeType = new BlackboardAttribute.Type(attributeTypeId, attributeTypeName,
4392  rs.getString("display_name"),
4394  this.typeIdToAttributeTypeMap.put(attributeTypeId, attributeType);
4395  this.typeNameToAttributeTypeMap.put(attributeTypeName, attributeType);
4396  }
4397 
4398  final BlackboardAttribute attr = new BlackboardAttribute(
4399  rs.getLong("artifact_id"),
4400  attributeType,
4401  rs.getString("source"),
4402  rs.getString("context"),
4403  rs.getInt("value_int32"),
4404  rs.getLong("value_int64"),
4405  rs.getDouble("value_double"),
4406  rs.getString("value_text"),
4407  rs.getBytes("value_byte"), this
4408  );
4409  attr.setParentDataSourceID(artifact.getDataSourceObjectID());
4410  attributes.add(attr);
4411  }
4412  return attributes;
4413  } catch (SQLException ex) {
4414  throw new TskCoreException("Error getting attributes for artifact, artifact id = " + artifact.getArtifactID(), ex);
4415  } finally {
4416  closeResultSet(rs);
4417  connection.close();
4419  }
4420  }
4421 
4434  public ArrayList<BlackboardAttribute> getMatchingAttributes(String whereClause) throws TskCoreException {
4435  CaseDbConnection connection = connections.getConnection();
4437  Statement s = null;
4438  ResultSet rs = null;
4439  try {
4440  s = connection.createStatement();
4441  rs = connection.executeQuery(s, "SELECT blackboard_attributes.artifact_id AS artifact_id, "
4442  + "blackboard_attributes.source AS source, blackboard_attributes.context AS context, "
4443  + "blackboard_attributes.attribute_type_id AS attribute_type_id, "
4444  + "blackboard_attributes.value_type AS value_type, blackboard_attributes.value_byte AS value_byte, "
4445  + "blackboard_attributes.value_text AS value_text, blackboard_attributes.value_int32 AS value_int32, "
4446  + "blackboard_attributes.value_int64 AS value_int64, blackboard_attributes.value_double AS value_double "
4447  + "FROM blackboard_attributes " + whereClause); //NON-NLS
4448  ArrayList<BlackboardAttribute> matches = new ArrayList<BlackboardAttribute>();
4449  while (rs.next()) {
4451  // attribute type is cached, so this does not necessarily call to the db
4452  type = this.getAttributeType(rs.getInt("attribute_type_id"));
4454  rs.getLong("artifact_id"),
4455  type,
4456  rs.getString("source"),
4457  rs.getString("context"),
4458  rs.getInt("value_int32"),
4459  rs.getLong("value_int64"),
4460  rs.getDouble("value_double"),
4461  rs.getString("value_text"),
4462  rs.getBytes("value_byte"), this
4463  );
4464  matches.add(attr);
4465  }
4466  return matches;
4467  } catch (SQLException ex) {
4468  throw new TskCoreException("Error getting attributes using this where clause: " + whereClause, ex);
4469  } finally {
4470  closeResultSet(rs);
4471  closeStatement(s);
4472  connection.close();
4474  }
4475  }
4476 
4488  public ArrayList<BlackboardArtifact> getMatchingArtifacts(String whereClause) throws TskCoreException {
4489  CaseDbConnection connection = connections.getConnection();
4491  ResultSet rs = null;
4492  Statement s = null;
4493  try {
4494  s = connection.createStatement();
4495  rs = connection.executeQuery(s, "SELECT blackboard_artifacts.artifact_id AS artifact_id, "
4496  + "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, "
4497  + "blackboard_artifacts.review_status_id AS review_status_id "
4498  + "FROM blackboard_artifacts " + whereClause); //NON-NLS
4499  ArrayList<BlackboardArtifact> matches = new ArrayList<BlackboardArtifact>();
4500  while (rs.next()) {
4501  BlackboardArtifact.Type type;
4502  // artifact type is cached, so this does not necessarily call to the db
4503  type = this.getArtifactType(rs.getInt("artifact_type_id"));
4504  BlackboardArtifact artifact = new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
4505  type.getTypeID(), type.getTypeName(), type.getDisplayName(),
4506  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")));
4507  matches.add(artifact);
4508  }
4509  return matches;
4510  } catch (SQLException ex) {
4511  throw new TskCoreException("Error getting attributes using this where clause: " + whereClause, ex);
4512  } finally {
4513  closeResultSet(rs);
4514  closeStatement(s);
4515  connection.close();
4517  }
4518  }
4519 
4533  public BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id) throws TskCoreException {
4534  BlackboardArtifact.Type type = getArtifactType(artifactTypeID);
4535  return newBlackboardArtifact(artifactTypeID, obj_id, type.getTypeName(), type.getDisplayName());
4536  }
4537 
4549  public BlackboardArtifact newBlackboardArtifact(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
4550  return newBlackboardArtifact(artifactType.getTypeID(), obj_id, artifactType.getLabel(), artifactType.getDisplayName());
4551  }
4552 
4565  BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id, long data_source_obj_id) throws TskCoreException {
4566  BlackboardArtifact.Type type = getArtifactType(artifactTypeID);
4567  return newBlackboardArtifact(artifactTypeID, obj_id, type.getTypeName(), type.getDisplayName(), data_source_obj_id);
4568  }
4569 
4570  private BlackboardArtifact newBlackboardArtifact(int artifact_type_id, long obj_id, String artifactTypeName, String artifactDisplayName) throws TskCoreException {
4571  try (CaseDbConnection connection = connections.getConnection()) {
4572  long data_source_obj_id = getDataSourceObjectId(connection, obj_id);
4573  return this.newBlackboardArtifact(artifact_type_id, obj_id, artifactTypeName, artifactDisplayName, data_source_obj_id);
4574  }
4575  }
4576 
4577  private BlackboardArtifact newBlackboardArtifact(int artifact_type_id, long obj_id, String artifactTypeName, String artifactDisplayName, long data_source_obj_id) throws TskCoreException {
4579  try (CaseDbConnection connection = connections.getConnection()) {
4580  long artifact_obj_id = addObject(obj_id, TskData.ObjectType.ARTIFACT.getObjectType(), connection);
4581  PreparedStatement statement = null;
4582  if (dbType == DbType.POSTGRESQL) {
4583  statement = connection.getPreparedStatement(PREPARED_STATEMENT.POSTGRESQL_INSERT_ARTIFACT, Statement.RETURN_GENERATED_KEYS);
4584  statement.clearParameters();
4585  statement.setLong(1, obj_id);
4586  statement.setLong(2, artifact_obj_id);
4587  statement.setLong(3, data_source_obj_id);
4588  statement.setInt(4, artifact_type_id);
4589 
4590  } else {
4591  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_ARTIFACT, Statement.RETURN_GENERATED_KEYS);
4592  statement.clearParameters();
4593  this.nextArtifactId++;
4594  statement.setLong(1, this.nextArtifactId);
4595  statement.setLong(2, obj_id);
4596  statement.setLong(3, artifact_obj_id);
4597  statement.setLong(4, data_source_obj_id);
4598  statement.setInt(5, artifact_type_id);
4599 
4600  }
4601  connection.executeUpdate(statement);
4602  try (ResultSet resultSet = statement.getGeneratedKeys()) {
4603  resultSet.next();
4604  return new BlackboardArtifact(this, resultSet.getLong(1), //last_insert_rowid()
4605  obj_id, artifact_obj_id, data_source_obj_id, artifact_type_id, artifactTypeName, artifactDisplayName, BlackboardArtifact.ReviewStatus.UNDECIDED, true);
4606  }
4607  } catch (SQLException ex) {
4608  throw new TskCoreException("Error creating a blackboard artifact", ex);
4609  } finally {
4611  }
4612  }
4613 
4626  boolean getContentHasChildren(Content content) throws TskCoreException {
4627  CaseDbConnection connection = connections.getConnection();
4629  ResultSet rs = null;
4630  try {
4631  // SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?
4632  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CHILD_OBJECTS_BY_PARENT);
4633  statement.clearParameters();
4634  statement.setLong(1, content.getId());
4635  rs = connection.executeQuery(statement);
4636  boolean hasChildren = false;
4637  if (rs.next()) {
4638  hasChildren = rs.getInt("count") > 0;
4639  }
4640  return hasChildren;
4641  } catch (SQLException e) {
4642  throw new TskCoreException("Error checking for children of parent " + content, e);
4643  } finally {
4644  closeResultSet(rs);
4645  connection.close();
4647  }
4648  }
4649 
4662  int getContentChildrenCount(Content content) throws TskCoreException {
4663 
4664  if (!this.getHasChildren(content)) {
4665  return 0;
4666  }
4667 
4668  CaseDbConnection connection = connections.getConnection();
4670  ResultSet rs = null;
4671  try {
4672  // SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?
4673  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CHILD_OBJECTS_BY_PARENT);
4674  statement.clearParameters();
4675  statement.setLong(1, content.getId());
4676  rs = connection.executeQuery(statement);
4677  int countChildren = -1;
4678  if (rs.next()) {
4679  countChildren = rs.getInt("count");
4680  }
4681  return countChildren;
4682  } catch (SQLException e) {
4683  throw new TskCoreException("Error checking for children of parent " + content, e);
4684  } finally {
4685  closeResultSet(rs);
4686  connection.close();
4688  }
4689  }
4690 
4702  List<Content> getAbstractFileChildren(Content parent, TSK_DB_FILES_TYPE_ENUM type) throws TskCoreException {
4703  CaseDbConnection connection = connections.getConnection();
4705  ResultSet rs = null;
4706  try {
4707  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT_AND_TYPE);
4708  statement.clearParameters();
4709  long parentId = parent.getId();
4710  statement.setLong(1, parentId);
4711  statement.setShort(2, type.getFileType());
4712  rs = connection.executeQuery(statement);
4713  return fileChildren(rs, connection, parentId);
4714  } catch (SQLException ex) {
4715  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4716  } finally {
4717  closeResultSet(rs);
4718  connection.close();
4720  }
4721  }
4722 
4732  List<Content> getAbstractFileChildren(Content parent) throws TskCoreException {
4733  CaseDbConnection connection = connections.getConnection();
4735  ResultSet rs = null;
4736  try {
4737  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT);
4738  statement.clearParameters();
4739  long parentId = parent.getId();
4740  statement.setLong(1, parentId);
4741  rs = connection.executeQuery(statement);
4742  return fileChildren(rs, connection, parentId);
4743  } catch (SQLException ex) {
4744  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4745  } finally {
4746  closeResultSet(rs);
4747  connection.close();
4749  }
4750  }
4751 
4763  List<Long> getAbstractFileChildrenIds(Content parent, TSK_DB_FILES_TYPE_ENUM type) throws TskCoreException {
4764  CaseDbConnection connection = connections.getConnection();
4766  ResultSet rs = null;
4767  try {
4768  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_IDS_BY_PARENT_AND_TYPE);
4769  statement.clearParameters();
4770  statement.setLong(1, parent.getId());
4771  statement.setShort(2, type.getFileType());
4772  rs = connection.executeQuery(statement);
4773  List<Long> children = new ArrayList<Long>();
4774  while (rs.next()) {
4775  children.add(rs.getLong("obj_id"));
4776  }
4777  return children;
4778  } catch (SQLException ex) {
4779  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4780  } finally {
4781  closeResultSet(rs);
4782  connection.close();
4784  }
4785  }
4786 
4796  List<Long> getAbstractFileChildrenIds(Content parent) throws TskCoreException {
4797  CaseDbConnection connection = connections.getConnection();
4799  ResultSet rs = null;
4800  try {
4801  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_IDS_BY_PARENT);
4802  statement.clearParameters();
4803  statement.setLong(1, parent.getId());
4804  rs = connection.executeQuery(statement);
4805  List<Long> children = new ArrayList<Long>();
4806  while (rs.next()) {
4807  children.add(rs.getLong("obj_id"));
4808  }
4809  return children;
4810  } catch (SQLException ex) {
4811  throw new TskCoreException("Error getting AbstractFile children for Content", ex);
4812  } finally {
4813  closeResultSet(rs);
4814  connection.close();
4816  }
4817  }
4818 
4829  List<Long> getBlackboardArtifactChildrenIds(Content parent) throws TskCoreException {
4830  CaseDbConnection connection = connections.getConnection();
4832  ResultSet rs = null;
4833  try {
4834  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_OBJECTIDS_BY_PARENT);
4835  statement.clearParameters();
4836  statement.setLong(1, parent.getId());
4837  rs = connection.executeQuery(statement);
4838  List<Long> children = new ArrayList<Long>();
4839  while (rs.next()) {
4840  children.add(rs.getLong("obj_id"));
4841  }
4842  return children;
4843  } catch (SQLException ex) {
4844  throw new TskCoreException("Error getting children for BlackboardArtifact", ex);
4845  } finally {
4846  closeResultSet(rs);
4847  connection.close();
4849  }
4850  }
4851 
4861  List<Content> getBlackboardArtifactChildren(Content parent) throws TskCoreException {
4862 
4863  long parentId = parent.getId();
4864  ArrayList<BlackboardArtifact> artsArray = getArtifactsHelper("blackboard_artifacts.obj_id = " + parentId + ";");
4865 
4866  List<Content> lc = new ArrayList<Content>();
4867  lc.addAll(artsArray);
4868  return lc;
4869  }
4870 
4879  Collection<ObjectInfo> getChildrenInfo(Content c) throws TskCoreException {
4880  CaseDbConnection connection = connections.getConnection();
4882  Statement s = null;
4883  ResultSet rs = null;
4884  try {
4885  s = connection.createStatement();
4886  rs = connection.executeQuery(s, "SELECT tsk_objects.obj_id AS obj_id, tsk_objects.type AS type " //NON-NLS
4887  + "FROM tsk_objects LEFT JOIN tsk_files " //NON-NLS
4888  + "ON tsk_objects.obj_id = tsk_files.obj_id " //NON-NLS
4889  + "WHERE tsk_objects.par_obj_id = " + c.getId()
4890  + " ORDER BY tsk_objects.obj_id"); //NON-NLS
4891  Collection<ObjectInfo> infos = new ArrayList<ObjectInfo>();
4892  while (rs.next()) {
4893  infos.add(new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")))); //NON-NLS
4894  }
4895  return infos;
4896  } catch (SQLException ex) {
4897  throw new TskCoreException("Error getting Children Info for Content", ex);
4898  } finally {
4899  closeResultSet(rs);
4900  closeStatement(s);
4901  connection.close();
4903  }
4904  }
4905 
4916  ObjectInfo getParentInfo(Content c) throws TskCoreException {
4917  return getParentInfo(c.getId());
4918  }
4919 
4930  ObjectInfo getParentInfo(long contentId) throws TskCoreException {
4931  CaseDbConnection connection = connections.getConnection();
4933  Statement s = null;
4934  ResultSet rs = null;
4935  try {
4936  s = connection.createStatement();
4937  rs = connection.executeQuery(s, "SELECT parent.obj_id AS obj_id, parent.type AS type " //NON-NLS
4938  + "FROM tsk_objects AS parent INNER JOIN tsk_objects AS child " //NON-NLS
4939  + "ON child.par_obj_id = parent.obj_id " //NON-NLS
4940  + "WHERE child.obj_id = " + contentId); //NON-NLS
4941  if (rs.next()) {
4942  return new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")));
4943  } else {
4944  return null;
4945  }
4946  } catch (SQLException ex) {
4947  throw new TskCoreException("Error getting Parent Info for Content: " + contentId, ex);
4948  } finally {
4949  closeResultSet(rs);
4950  closeStatement(s);
4951  connection.close();
4953  }
4954  }
4955 
4966  Directory getParentDirectory(FsContent fsc) throws TskCoreException {
4967  if (fsc.isRoot()) {
4968  // Given FsContent is a root object and can't have parent directory
4969  return null;
4970  } else {
4971  ObjectInfo parentInfo = getParentInfo(fsc);
4972  if (parentInfo == null) {
4973  return null;
4974  }
4975  Directory parent = null;
4976  if (parentInfo.type == ObjectType.ABSTRACTFILE) {
4977  parent = getDirectoryById(parentInfo.id, fsc.getFileSystem());
4978  } else {
4979  throw new TskCoreException("Parent of FsContent (id: " + fsc.getId() + ") has wrong type to be directory: " + parentInfo.type);
4980  }
4981  return parent;
4982  }
4983  }
4984 
4996  public Content getContentById(long id) throws TskCoreException {
4997  // First check to see if this exists in our frequently used content cache.
4998  Content content = frequentlyUsedContentMap.get(id);
4999  if (null != content) {
5000  return content;
5001  }
5002 
5003  CaseDbConnection connection = connections.getConnection();
5005  Statement s = null;
5006  ResultSet rs = null;
5007  long parentId;
5008  TskData.ObjectType type;
5009 
5010  try {
5011  s = connection.createStatement();
5012  rs = connection.executeQuery(s, "SELECT * FROM tsk_objects WHERE obj_id = " + id + " LIMIT 1"); //NON-NLS
5013  if (!rs.next()) {
5014  return null;
5015  }
5016  parentId = rs.getLong("par_obj_id"); //NON-NLS
5017  type = TskData.ObjectType.valueOf(rs.getShort("type")); //NON-NLS
5018  } catch (SQLException ex) {
5019  throw new TskCoreException("Error getting Content by ID.", ex);
5020  } finally {
5021  closeResultSet(rs);
5022  closeStatement(s);
5023  connection.close();
5025  }
5026 
5027  // Construct the object
5028  switch (type) {
5029  case IMG:
5030  content = getImageById(id);
5031  frequentlyUsedContentMap.put(id, content);
5032  break;
5033  case VS:
5034  content = getVolumeSystemById(id, parentId);
5035  break;
5036  case VOL:
5037  content = getVolumeById(id, parentId);
5038  frequentlyUsedContentMap.put(id, content);
5039  break;
5040  case POOL:
5041  content = getPoolById(id, parentId);
5042  break;
5043  case FS:
5044  content = getFileSystemById(id, parentId);
5045  frequentlyUsedContentMap.put(id, content);
5046  break;
5047  case ABSTRACTFILE:
5048  content = getAbstractFileById(id);
5049 
5050  // Add virtual and root directories to frequently used map.
5051  // Calling isRoot() on local directories goes up the entire directory structure
5052  // and they can only be the root of portable cases, so skip trying to add
5053  // them to the cache.
5054  if (((AbstractFile) content).isVirtual()
5055  || ((!(content instanceof LocalDirectory)) && ((AbstractFile) content).isRoot())) {
5056  frequentlyUsedContentMap.put(id, content);
5057  }
5058  break;
5059  case ARTIFACT:
5060  content = getArtifactById(id);
5061  break;
5062  case REPORT:
5063  content = getReportById(id);
5064  break;
5065  default:
5066  throw new TskCoreException("Could not obtain Content object with ID: " + id);
5067  }
5068 
5069  return content;
5070  }
5071 
5079  String getFilePath(long id) {
5080  CaseDbConnection connection;
5081  try {
5082  connection = connections.getConnection();
5083  } catch (TskCoreException ex) {
5084  logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
5085  return null;
5086  }
5087  String filePath = null;
5089  ResultSet rs = null;
5090  try {
5091  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_FOR_FILE);
5092  statement.clearParameters();
5093  statement.setLong(1, id);
5094  rs = connection.executeQuery(statement);
5095  if (rs.next()) {
5096  filePath = rs.getString("path");
5097  }
5098  } catch (SQLException ex) {
5099  logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
5100  } finally {
5101  closeResultSet(rs);
5102  connection.close();
5104  }
5105  return filePath;
5106  }
5107 
5115  TskData.EncodingType getEncodingType(long id) {
5116  CaseDbConnection connection;
5117  try {
5118  connection = connections.getConnection();
5119  } catch (TskCoreException ex) {
5120  logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
5121  return null;
5122  }
5123  TskData.EncodingType type = TskData.EncodingType.NONE;
5125  ResultSet rs = null;
5126  try {
5127  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ENCODING_FOR_FILE);
5128  statement.clearParameters();
5129  statement.setLong(1, id);
5130  rs = connection.executeQuery(statement);
5131  if (rs.next()) {
5132  type = TskData.EncodingType.valueOf(rs.getInt(1));
5133  }
5134  } catch (SQLException ex) {
5135  logger.log(Level.SEVERE, "Error getting encoding type for file " + id, ex); //NON-NLS
5136  } finally {
5137  closeResultSet(rs);
5138  connection.close();
5140  }
5141  return type;
5142  }
5143 
5152  String getFileParentPath(long objectId, CaseDbConnection connection) {
5153  String parentPath = null;
5155  ResultSet rs = null;
5156  try {
5157  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_PATH_FOR_FILE);
5158  statement.clearParameters();
5159  statement.setLong(1, objectId);
5160  rs = connection.executeQuery(statement);
5161  if (rs.next()) {
5162  parentPath = rs.getString("parent_path");
5163  }
5164  } catch (SQLException ex) {
5165  logger.log(Level.SEVERE, "Error getting file parent_path for file " + objectId, ex); //NON-NLS
5166  } finally {
5167  closeResultSet(rs);
5169  }
5170  return parentPath;
5171  }
5172 
5181  String getFileName(long objectId, CaseDbConnection connection) {
5182  String fileName = null;
5184  ResultSet rs = null;
5185  try {
5186  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_NAME);
5187  statement.clearParameters();
5188  statement.setLong(1, objectId);
5189  rs = connection.executeQuery(statement);
5190  if (rs.next()) {
5191  fileName = rs.getString("name");
5192  }
5193  } catch (SQLException ex) {
5194  logger.log(Level.SEVERE, "Error getting file parent_path for file " + objectId, ex); //NON-NLS
5195  } finally {
5196  closeResultSet(rs);
5198  }
5199  return fileName;
5200  }
5201 
5212  DerivedFile.DerivedMethod getDerivedMethod(long id) throws TskCoreException {
5213  CaseDbConnection connection = connections.getConnection();
5214  DerivedFile.DerivedMethod method = null;
5216  ResultSet rs1 = null;
5217  ResultSet rs2 = null;
5218  try {
5219  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_DERIVED_FILE);
5220  statement.clearParameters();
5221  statement.setLong(1, id);
5222  rs1 = connection.executeQuery(statement);
5223  if (rs1.next()) {
5224  int method_id = rs1.getInt("derived_id");
5225  String rederive = rs1.getString("rederive");
5226  method = new DerivedFile.DerivedMethod(method_id, rederive);
5227  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_DERIVATION_METHOD);
5228  statement.clearParameters();
5229  statement.setInt(1, method_id);
5230  rs2 = connection.executeQuery(statement);
5231  if (rs2.next()) {
5232  method.setToolName(rs2.getString("tool_name"));
5233  method.setToolVersion(rs2.getString("tool_version"));
5234  method.setOther(rs2.getString("other"));
5235  }
5236  }
5237  } catch (SQLException e) {
5238  logger.log(Level.SEVERE, "Error getting derived method for file: " + id, e); //NON-NLS
5239  } finally {
5240  closeResultSet(rs2);
5241  closeResultSet(rs1);
5242  connection.close();
5244  }
5245  return method;
5246  }
5247 
5258  public AbstractFile getAbstractFileById(long id) throws TskCoreException {
5259  CaseDbConnection connection = connections.getConnection();
5260  try {
5261  return getAbstractFileById(id, connection);
5262  } finally {
5263  connection.close();
5264  }
5265  }
5266 
5279  AbstractFile getAbstractFileById(long objectId, CaseDbConnection connection) throws TskCoreException {
5281  ResultSet rs = null;
5282  try {
5283  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_BY_ID);
5284  statement.clearParameters();
5285  statement.setLong(1, objectId);
5286  rs = connection.executeQuery(statement);
5287  List<AbstractFile> files = resultSetToAbstractFiles(rs, connection);
5288  if (files.size() > 0) {
5289  return files.get(0);
5290  } else {
5291  return null;
5292  }
5293  } catch (SQLException ex) {
5294  throw new TskCoreException("Error getting file by id, id = " + objectId, ex);
5295  } finally {
5296  closeResultSet(rs);
5298  }
5299  }
5300 
5311  public BlackboardArtifact getArtifactById(long id) throws TskCoreException {
5312  CaseDbConnection connection = connections.getConnection();
5314  ResultSet rs = null;
5315  try {
5316  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_BY_ARTIFACT_OBJ_ID);
5317  statement.clearParameters();
5318  statement.setLong(1, id);
5319  rs = connection.executeQuery(statement);
5320  List<BlackboardArtifact> artifacts = resultSetToArtifacts(rs);
5321  if (artifacts.size() > 0) {
5322  return artifacts.get(0);
5323  } else {
5324  return null;
5325  }
5326  } catch (SQLException ex) {
5327  throw new TskCoreException("Error getting artifacts by artifact_obj_id, artifact_obj_id = " + id, ex);
5328  } finally {
5329  closeResultSet(rs);
5330  connection.close();
5332  }
5333  }
5334 
5345  public BlackboardArtifact getArtifactByArtifactId(long id) throws TskCoreException {
5346  CaseDbConnection connection = connections.getConnection();
5348  ResultSet rs = null;
5349  try {
5350  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_BY_ARTIFACT_ID);
5351  statement.clearParameters();
5352  statement.setLong(1, id);
5353  rs = connection.executeQuery(statement);
5354  List<BlackboardArtifact> artifacts = resultSetToArtifacts(rs);
5355  if (artifacts.size() > 0) {
5356  return artifacts.get(0);
5357  } else {
5358  return null;
5359  }
5360  } catch (SQLException ex) {
5361  throw new TskCoreException("Error getting artifacts by artifact id, artifact id = " + id, ex);
5362  } finally {
5363  closeResultSet(rs);
5364  connection.close();
5366  }
5367  }
5368 
5381  private long getFileSystemId(long fileId, CaseDbConnection connection) {
5383  ResultSet rs = null;
5384  long ret = -1;
5385  try {
5386  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_SYSTEM_BY_OBJECT);
5387  statement.clearParameters();
5388  statement.setLong(1, fileId);
5389  rs = connection.executeQuery(statement);
5390  if (rs.next()) {
5391  ret = rs.getLong("fs_obj_id");
5392  if (ret == 0) {
5393  ret = -1;
5394  }
5395  }
5396  } catch (SQLException e) {
5397  logger.log(Level.SEVERE, "Error checking file system id of a file, id = " + fileId, e); //NON-NLS
5398  } finally {
5399  closeResultSet(rs);
5401  }
5402  return ret;
5403  }
5404 
5416  public boolean isFileFromSource(Content dataSource, long fileId) throws TskCoreException {
5417  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
5418  CaseDbConnection connection = connections.getConnection();
5420  Statement statement = null;
5421  ResultSet resultSet = null;
5422  try {
5423  statement = connection.createStatement();
5424  resultSet = connection.executeQuery(statement, query);
5425  resultSet.next();
5426  return (resultSet.getLong("count") > 0L);
5427  } catch (SQLException ex) {
5428  throw new TskCoreException(String.format("Error executing query %s", query), ex);
5429  } finally {
5430  closeResultSet(resultSet);
5431  closeStatement(statement);
5432  connection.close();
5434  }
5435  }
5436 
5448  public List<AbstractFile> findFiles(Content dataSource, String fileName) throws TskCoreException {
5449  List<AbstractFile> files = new ArrayList<AbstractFile>();
5450  CaseDbConnection connection = connections.getConnection();
5452  ResultSet resultSet = null;
5453  try {
5454  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_DATA_SOURCE_AND_NAME);
5455  statement.clearParameters();
5456  statement.setString(1, fileName.toLowerCase());
5457  statement.setLong(2, dataSource.getId());
5458  resultSet = connection.executeQuery(statement);
5459  files.addAll(resultSetToAbstractFiles(resultSet, connection));
5460  } catch (SQLException e) {
5461  throw new TskCoreException(bundle.getString("SleuthkitCase.findFiles.exception.msg3.text"), e);
5462  } finally {
5463  closeResultSet(resultSet);
5464  connection.close();
5466  }
5467  return files;
5468  }
5469 
5483  public List<AbstractFile> findFiles(Content dataSource, String fileName, String dirSubString) throws TskCoreException {
5484  List<AbstractFile> files = new ArrayList<AbstractFile>();
5485  CaseDbConnection connection = connections.getConnection();
5487  ResultSet resultSet = null;
5488  try {
5489  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_DATA_SOURCE_AND_PARENT_PATH_AND_NAME);
5490  statement.clearParameters();
5491  statement.setString(1, fileName.toLowerCase());
5492  statement.setString(2, "%" + dirSubString.toLowerCase() + "%"); //NON-NLS
5493  statement.setLong(3, dataSource.getId());
5494  resultSet = connection.executeQuery(statement);
5495  files.addAll(resultSetToAbstractFiles(resultSet, connection));
5496  } catch (SQLException e) {
5497  throw new TskCoreException(bundle.getString("SleuthkitCase.findFiles3.exception.msg3.text"), e);
5498  } finally {
5499  closeResultSet(resultSet);
5500  connection.close();
5502  }
5503  return files;
5504  }
5505 
5517  public VirtualDirectory addVirtualDirectory(long parentId, String directoryName) throws TskCoreException {
5518  CaseDbTransaction localTrans = beginTransaction();
5519  try {
5520  VirtualDirectory newVD = addVirtualDirectory(parentId, directoryName, localTrans);
5521  localTrans.commit();
5522  localTrans = null;
5523  return newVD;
5524  } finally {
5525  if (null != localTrans) {
5526  try {
5527  localTrans.rollback();
5528  } catch (TskCoreException ex2) {
5529  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
5530  }
5531  }
5532  }
5533  }
5534 
5547  long addObject(long parentId, int objectType, CaseDbConnection connection) throws SQLException {
5548  ResultSet resultSet = null;
5550  try {
5551  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
5552  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OBJECT, Statement.RETURN_GENERATED_KEYS);
5553  statement.clearParameters();
5554  if (parentId != 0) {
5555  statement.setLong(1, parentId);
5556  } else {
5557  statement.setNull(1, java.sql.Types.BIGINT);
5558  }
5559  statement.setInt(2, objectType);
5560  connection.executeUpdate(statement);
5561  resultSet = statement.getGeneratedKeys();
5562 
5563  if (resultSet.next()) {
5564  if (parentId != 0) {
5565  setHasChildren(parentId);
5566  }
5567  return resultSet.getLong(1); //last_insert_rowid()
5568  } else {
5569  throw new SQLException("Error inserting object with parent " + parentId + " into tsk_objects");
5570  }
5571  } finally {
5572  closeResultSet(resultSet);
5574  }
5575  }
5576 
5594  public VirtualDirectory addVirtualDirectory(long parentId, String directoryName, CaseDbTransaction transaction) throws TskCoreException {
5595  if (transaction == null) {
5596  throw new TskCoreException("Passed null CaseDbTransaction");
5597  }
5598 
5599  ResultSet resultSet = null;
5600  try {
5601  // Get the parent path.
5602  CaseDbConnection connection = transaction.getConnection();
5603 
5604  String parentPath;
5605  Content parent = this.getAbstractFileById(parentId, connection);
5606  if (parent instanceof AbstractFile) {
5607  if (isRootDirectory((AbstractFile) parent, transaction)) {
5608  parentPath = "/";
5609  } else {
5610  parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + "/"; //NON-NLS
5611  }
5612  } else {
5613  // The parent was either null or not an abstract file
5614  parentPath = "/";
5615  }
5616 
5617  // Insert a row for the virtual directory into the tsk_objects table.
5618  long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
5619 
5620  // Insert a row for the virtual directory into the tsk_files table.
5621  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
5622  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id,extension)
5623  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
5624  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
5625  statement.clearParameters();
5626  statement.setLong(1, newObjId);
5627 
5628  // If the parent is part of a file system, grab its file system ID
5629  if (0 != parentId) {
5630  long parentFs = this.getFileSystemId(parentId, connection);
5631  if (parentFs != -1) {
5632  statement.setLong(2, parentFs);
5633  } else {
5634  statement.setNull(2, java.sql.Types.BIGINT);
5635  }
5636  } else {
5637  statement.setNull(2, java.sql.Types.BIGINT);
5638  }
5639 
5640  // name
5641  statement.setString(3, directoryName);
5642 
5643  //type
5644  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType());
5645  statement.setShort(5, (short) 1);
5646 
5647  //flags
5649  statement.setShort(6, dirType.getValue());
5651  statement.setShort(7, metaType.getValue());
5652 
5653  //allocated
5655  statement.setShort(8, dirFlag.getValue());
5656  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
5657  | TSK_FS_META_FLAG_ENUM.USED.getValue());
5658  statement.setShort(9, metaFlags);
5659 
5660  //size
5661  statement.setLong(10, 0);
5662 
5663  // nulls for params 11-14
5664  statement.setNull(11, java.sql.Types.BIGINT);
5665  statement.setNull(12, java.sql.Types.BIGINT);
5666  statement.setNull(13, java.sql.Types.BIGINT);
5667  statement.setNull(14, java.sql.Types.BIGINT);
5668 
5669  statement.setNull(15, java.sql.Types.VARCHAR); // MD5
5670  statement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
5671  statement.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
5672  statement.setNull(18, java.sql.Types.VARCHAR); // MIME type
5673 
5674  // parent path
5675  statement.setString(19, parentPath);
5676 
5677  // data source object id (same as object id if this is a data source)
5678  long dataSourceObjectId;
5679  if (0 == parentId) {
5680  dataSourceObjectId = newObjId;
5681  } else {
5682  dataSourceObjectId = getDataSourceObjectId(connection, parentId);
5683  }
5684  statement.setLong(20, dataSourceObjectId);
5685 
5686  //extension, since this is not really file we just set it to null
5687  statement.setString(21, null);
5688  connection.executeUpdate(statement);
5689 
5690  return new VirtualDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType,
5691  metaType, dirFlag, metaFlags, null, null, FileKnown.UNKNOWN,
5692  parentPath);
5693  } catch (SQLException e) {
5694  throw new TskCoreException("Error creating virtual directory '" + directoryName + "'", e);
5695  } finally {
5696  closeResultSet(resultSet);
5697  }
5698  }
5699 
5712  public LocalDirectory addLocalDirectory(long parentId, String directoryName) throws TskCoreException {
5713  CaseDbTransaction localTrans = beginTransaction();
5714  try {
5715  LocalDirectory newLD = addLocalDirectory(parentId, directoryName, localTrans);
5716  localTrans.commit();
5717  return newLD;
5718  } catch (TskCoreException ex) {
5719  try {
5720  localTrans.rollback();
5721  } catch (TskCoreException ex2) {
5722  logger.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
5723  }
5724  throw ex;
5725  }
5726  }
5727 
5745  public LocalDirectory addLocalDirectory(long parentId, String directoryName, CaseDbTransaction transaction) throws TskCoreException {
5746  if (transaction == null) {
5747  throw new TskCoreException("Passed null CaseDbTransaction");
5748  }
5749 
5750  ResultSet resultSet = null;
5751  try {
5752  // Get the parent path.
5753  CaseDbConnection connection = transaction.getConnection();
5754  AbstractFile parent = getAbstractFileById(parentId, connection);
5755  String parentPath;
5756  if ((parent == null) || isRootDirectory(parent, transaction)) {
5757  parentPath = "/";
5758  } else {
5759  parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS
5760  }
5761 
5762  // Insert a row for the local directory into the tsk_objects table.
5763  long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
5764 
5765  // Insert a row for the local directory into the tsk_files table.
5766  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
5767  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, known, mime_type, parent_path, data_source_obj_id)
5768  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
5769  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
5770  statement.clearParameters();
5771  statement.setLong(1, newObjId);
5772 
5773  // The parent of a local directory will never be a file system
5774  statement.setNull(2, java.sql.Types.BIGINT);
5775 
5776  // name
5777  statement.setString(3, directoryName);
5778 
5779  //type
5780  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR.getFileType());
5781  statement.setShort(5, (short) 1);
5782 
5783  //flags
5785  statement.setShort(6, dirType.getValue());
5787  statement.setShort(7, metaType.getValue());
5788 
5789  //allocated
5791  statement.setShort(8, dirFlag.getValue());
5792  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
5793  | TSK_FS_META_FLAG_ENUM.USED.getValue());
5794  statement.setShort(9, metaFlags);
5795 
5796  //size
5797  statement.setLong(10, 0);
5798 
5799  // nulls for params 11-14
5800  statement.setNull(11, java.sql.Types.BIGINT);
5801  statement.setNull(12, java.sql.Types.BIGINT);
5802  statement.setNull(13, java.sql.Types.BIGINT);
5803  statement.setNull(14, java.sql.Types.BIGINT);
5804 
5805  statement.setNull(15, java.sql.Types.VARCHAR); // MD5
5806  statement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
5807  statement.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
5808  statement.setNull(18, java.sql.Types.VARCHAR); // MIME type
5809 
5810  // parent path
5811  statement.setString(19, parentPath);
5812 
5813  // data source object id
5814  long dataSourceObjectId = getDataSourceObjectId(connection, parentId);
5815  statement.setLong(20, dataSourceObjectId);
5816 
5817  //extension, since this is a directory we just set it to null
5818  statement.setString(21, null);
5819 
5820  connection.executeUpdate(statement);
5821 
5822  return new LocalDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType,
5823  metaType, dirFlag, metaFlags, null, null, FileKnown.UNKNOWN,
5824  parentPath);
5825  } catch (SQLException e) {
5826  throw new TskCoreException("Error creating local directory '" + directoryName + "'", e);
5827  } finally {
5828  closeResultSet(resultSet);
5829  }
5830  }
5831 
5851  public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, CaseDbTransaction transaction) throws TskCoreException {
5853  Statement statement = null;
5854  try {
5855  // Insert a row for the root virtual directory of the data source
5856  // into the tsk_objects table.
5857  CaseDbConnection connection = transaction.getConnection();
5858  long newObjId = addObject(0, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
5859 
5860  // Insert a row for the virtual directory of the data source into
5861  // the data_source_info table.
5862  statement = connection.createStatement();
5863  statement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) "
5864  + "VALUES(" + newObjId + ", '" + deviceId + "', '" + timeZone + "');");
5865 
5866  // Insert a row for the root virtual directory of the data source
5867  // into the tsk_files table. Note that its data source object id is
5868  // its own object id.
5869  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path,
5870  // dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime,
5871  // atime, mtime, md5, known, mime_type, parent_path, data_source_obj_id, extension)
5872  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
5873  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
5874  preparedStatement.clearParameters();
5875  preparedStatement.setLong(1, newObjId);
5876  preparedStatement.setNull(2, java.sql.Types.BIGINT);
5877  preparedStatement.setString(3, rootDirectoryName);
5878  preparedStatement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType());
5879  preparedStatement.setShort(5, (short) 1);
5881  preparedStatement.setShort(6, TSK_FS_NAME_TYPE_ENUM.DIR.getValue());
5883  preparedStatement.setShort(7, metaType.getValue());
5885  preparedStatement.setShort(8, dirFlag.getValue());
5886  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
5887  | TSK_FS_META_FLAG_ENUM.USED.getValue());
5888  preparedStatement.setShort(9, metaFlags);
5889  preparedStatement.setLong(10, 0);
5890  preparedStatement.setNull(11, java.sql.Types.BIGINT);
5891  preparedStatement.setNull(12, java.sql.Types.BIGINT);
5892  preparedStatement.setNull(13, java.sql.Types.BIGINT);
5893  preparedStatement.setNull(14, java.sql.Types.BIGINT);
5894  preparedStatement.setNull(15, java.sql.Types.VARCHAR); // MD5
5895  preparedStatement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
5896  preparedStatement.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
5897  preparedStatement.setNull(18, java.sql.Types.VARCHAR); // MIME type
5898  String parentPath = "/"; //NON-NLS
5899  preparedStatement.setString(19, parentPath);
5900  preparedStatement.setLong(20, newObjId);
5901  preparedStatement.setString(21, null); //extension, just set it to null
5902  connection.executeUpdate(preparedStatement);
5903 
5904  return new LocalFilesDataSource(this, newObjId, newObjId, deviceId, rootDirectoryName, dirType, metaType, dirFlag, metaFlags, timeZone, null, null, FileKnown.UNKNOWN, parentPath);
5905 
5906  } catch (SQLException ex) {
5907  throw new TskCoreException(String.format("Error creating local files data source with device id %s and directory name %s", deviceId, rootDirectoryName), ex);
5908  } finally {
5909  closeStatement(statement);
5911  }
5912  }
5913 
5933  public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths,
5934  String timezone, String md5, String sha1, String sha256,
5935  String deviceId,
5936  CaseDbTransaction transaction) throws TskCoreException {
5938  Statement statement = null;
5939  try {
5940  // Insert a row for the Image into the tsk_objects table.
5941  CaseDbConnection connection = transaction.getConnection();
5942  long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
5943 
5944  // Add a row to tsk_image_info
5945  // INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
5946  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO);
5947  preparedStatement.clearParameters();
5948  preparedStatement.setLong(1, newObjId);
5949  preparedStatement.setShort(2, (short) type.getValue());
5950  preparedStatement.setLong(3, sectorSize);
5951  preparedStatement.setString(4, timezone);
5952  //prevent negative size
5953  long savedSize = size < 0 ? 0 : size;
5954  preparedStatement.setLong(5, savedSize);
5955  preparedStatement.setString(6, md5);
5956  preparedStatement.setString(7, sha1);
5957  preparedStatement.setString(8, sha256);
5958  preparedStatement.setString(9, displayName);
5959  connection.executeUpdate(preparedStatement);
5960 
5961  // If there are paths, add them to tsk_image_names
5962  for (int i = 0; i < imagePaths.size(); i++) {
5963  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
5964  preparedStatement.clearParameters();
5965  preparedStatement.setLong(1, newObjId);
5966  preparedStatement.setString(2, imagePaths.get(i));
5967  preparedStatement.setLong(3, i);
5968  connection.executeUpdate(preparedStatement);
5969  }
5970 
5971  // Add a row to data_source_info
5972  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DATA_SOURCE_INFO);
5973  statement = connection.createStatement();
5974  preparedStatement.setLong(1, newObjId);
5975  preparedStatement.setString(2, deviceId);
5976  preparedStatement.setString(3, timezone);
5977  connection.executeUpdate(preparedStatement);
5978 
5979  // Create the new Image object
5980  String name = displayName;
5981  if (name == null || name.isEmpty()) {
5982  if (imagePaths.size() > 0) {
5983  String path = imagePaths.get(0);
5984  name = (new java.io.File(path)).getName();
5985  } else {
5986  name = "";
5987  }
5988  }
5989  return new Image(this, newObjId, type.getValue(), deviceId, sectorSize, name,
5990  imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, savedSize);
5991  } catch (SQLException ex) {
5992  if (!imagePaths.isEmpty()) {
5993  throw new TskCoreException(String.format("Error adding image with path %s to database", imagePaths.get(0)), ex);
5994  } else {
5995  throw new TskCoreException(String.format("Error adding image with display name %s to database", displayName), ex);
5996  }
5997  } finally {
5998  closeStatement(statement);
6000  }
6001  }
6002 
6016  public VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset,
6017  long blockSize, CaseDbTransaction transaction) throws TskCoreException {
6019  try {
6020  // Insert a row for the VolumeSystem into the tsk_objects table.
6021  CaseDbConnection connection = transaction.getConnection();
6022  long newObjId = addObject(parentObjId, TskData.ObjectType.VS.getObjectType(), connection);
6023 
6024  // Add a row to tsk_vs_info
6025  // INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size)
6026  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_INFO);
6027  preparedStatement.clearParameters();
6028  preparedStatement.setLong(1, newObjId);
6029  preparedStatement.setShort(2, (short) type.getVsType());
6030  preparedStatement.setLong(3, imgOffset);
6031  preparedStatement.setLong(4, blockSize);
6032  connection.executeUpdate(preparedStatement);
6033 
6034  // Create the new VolumeSystem object
6035  return new VolumeSystem(this, newObjId, "", type.getVsType(), imgOffset, blockSize);
6036  } catch (SQLException ex) {
6037  throw new TskCoreException(String.format("Error creating volume system with parent ID %d and image offset %d",
6038  parentObjId, imgOffset), ex);
6039  } finally {
6041  }
6042  }
6043 
6059  public Volume addVolume(long parentObjId, long addr, long start, long length, String desc,
6060  long flags, CaseDbTransaction transaction) throws TskCoreException {
6062  Statement statement = null;
6063  try {
6064  // Insert a row for the Volume into the tsk_objects table.
6065  CaseDbConnection connection = transaction.getConnection();
6066  long newObjId = addObject(parentObjId, TskData.ObjectType.VOL.getObjectType(), connection);
6067 
6068  // Add a row to tsk_vs_parts
6069  // INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags)
6070  PreparedStatement preparedStatement;
6071  if (this.dbType == DbType.POSTGRESQL) {
6072  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_POSTGRESQL);
6073  } else {
6074  preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_SQLITE);
6075  }
6076  preparedStatement.clearParameters();
6077  preparedStatement.setLong(1, newObjId);
6078  preparedStatement.setLong(2, addr);
6079  preparedStatement.setLong(3, start);
6080  preparedStatement.setLong(4, length);
6081  preparedStatement.setString(5, desc);
6082  preparedStatement.setShort(6, (short) flags);
6083  connection.executeUpdate(preparedStatement);
6084 
6085  // Create the new Volume object
6086  return new Volume(this, newObjId, addr, start, length, flags, desc);
6087  } catch (SQLException ex) {
6088  throw new TskCoreException(String.format("Error creating volume with address %d and parent ID %d", addr, parentObjId), ex);
6089  } finally {
6090  closeStatement(statement);
6092  }
6093  }
6094 
6106  public Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTransaction transaction) throws TskCoreException {
6108  Statement statement = null;
6109  try {
6110  // Insert a row for the Pool into the tsk_objects table.
6111  CaseDbConnection connection = transaction.getConnection();
6112  long newObjId = addObject(parentObjId, TskData.ObjectType.POOL.getObjectType(), connection);
6113 
6114  // Add a row to tsk_pool_info
6115  // INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)
6116  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_POOL_INFO);
6117  preparedStatement.clearParameters();
6118  preparedStatement.setLong(1, newObjId);
6119  preparedStatement.setShort(2, type.getValue());
6120  connection.executeUpdate(preparedStatement);
6121 
6122  // Create the new Pool object
6123  return new Pool(this, newObjId, type.getName(), type.getValue());
6124  } catch (SQLException ex) {
6125  throw new TskCoreException(String.format("Error creating pool with type %d and parent ID %d", type.getValue(), parentObjId), ex);
6126  } finally {
6127  closeStatement(statement);
6129  }
6130  }
6131 
6150  public FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS_TYPE_ENUM type, long blockSize, long blockCount,
6151  long rootInum, long firstInum, long lastInum, String displayName,
6152  CaseDbTransaction transaction) throws TskCoreException {
6154  Statement statement = null;
6155  try {
6156  // Insert a row for the FileSystem into the tsk_objects table.
6157  CaseDbConnection connection = transaction.getConnection();
6158  long newObjId = addObject(parentObjId, TskData.ObjectType.FS.getObjectType(), connection);
6159 
6160  // Get the data source object ID
6161  long dataSourceId = getDataSourceObjectId(connection, newObjId);
6162 
6163  // Add a row to tsk_fs_info
6164  // 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)
6165  PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FS_INFO);
6166  preparedStatement.clearParameters();
6167  preparedStatement.setLong(1, newObjId);
6168  preparedStatement.setLong(2, dataSourceId);
6169  preparedStatement.setLong(3, imgOffset);
6170  preparedStatement.setInt(4, type.getValue());
6171  preparedStatement.setLong(5, blockSize);
6172  preparedStatement.setLong(6, blockCount);
6173  preparedStatement.setLong(7, rootInum);
6174  preparedStatement.setLong(8, firstInum);
6175  preparedStatement.setLong(9, lastInum);
6176  preparedStatement.setString(10, displayName);
6177  connection.executeUpdate(preparedStatement);
6178 
6179  // Create the new FileSystem object
6180  return new FileSystem(this, newObjId, displayName, imgOffset, type, blockSize, blockCount, rootInum,
6181  firstInum, lastInum);
6182  } catch (SQLException ex) {
6183  throw new TskCoreException(String.format("Error creating file system with image offset %d and parent ID %d",
6184  imgOffset, parentObjId), ex);
6185  } finally {
6186  closeStatement(statement);
6188  }
6189  }
6190 
6216  public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
6217  String fileName,
6218  long metaAddr, int metaSeq,
6219  TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
6220  TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
6221  long ctime, long crtime, long atime, long mtime,
6222  boolean isFile, Content parent) throws TskCoreException {
6223 
6224  TimelineManager timelineManager = getTimelineManager();
6225 
6226  CaseDbTransaction transaction = beginTransaction();
6227  Statement queryStatement = null;
6228  try {
6229  CaseDbConnection connection = transaction.getConnection();
6230 
6231  // Insert a row for the local/logical file into the tsk_objects table.
6232  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6233  long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6234 
6235  String parentPath;
6236 
6237  if (parent instanceof AbstractFile) {
6238  AbstractFile parentFile = (AbstractFile) parent;
6239  if (isRootDirectory(parentFile, transaction)) {
6240  parentPath = "/";
6241  } else {
6242  parentPath = parentFile.getParentPath() + parent.getName() + "/"; //NON-NLS
6243  }
6244  } else {
6245  parentPath = "/";
6246  }
6247 
6248  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_SYSTEM_FILE);
6249  statement.clearParameters();
6250  statement.setLong(1, objectId); // obj_is
6251  statement.setLong(2, fsObjId); // fs_obj_id
6252  statement.setLong(3, dataSourceObjId); // data_source_obj_id
6253  statement.setShort(4, (short) attrType.getValue()); // attr_type
6254  statement.setInt(5, attrId); // attr_id
6255  statement.setString(6, fileName); // name
6256  statement.setLong(7, metaAddr); // meta_addr
6257  statement.setInt(8, metaSeq); // meta_addr
6258  statement.setShort(9, TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType()); //type
6259  statement.setShort(10, (short) 1); // has_path
6261  statement.setShort(11, dirType.getValue()); // dir_type
6263  statement.setShort(12, metaType.getValue()); // meta_type
6264  statement.setShort(13, dirFlag.getValue()); // dir_flags
6265  statement.setShort(14, metaFlags); // meta_flags
6266  statement.setLong(15, size < 0 ? 0 : size);
6267  statement.setLong(16, ctime);
6268  statement.setLong(17, crtime);
6269  statement.setLong(18, atime);
6270  statement.setLong(19, mtime);
6271  statement.setString(20, parentPath);
6272  final String extension = extractExtension(fileName);
6273  statement.setString(21, extension);
6274 
6275  connection.executeUpdate(statement);
6276 
6277  DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags,
6278  size, ctime, crtime, atime, mtime, null, null, null, parentPath, null, parent.getId(), null, null, extension);
6279 
6280  timelineManager.addEventsForNewFile(derivedFile, connection);
6281 
6282  transaction.commit();
6283  transaction = null;
6284 
6285  return new org.sleuthkit.datamodel.File(this, objectId, dataSourceObjId, fsObjId,
6286  attrType, attrId, fileName, metaAddr, metaSeq,
6287  dirType, metaType, dirFlag, metaFlags,
6288  size, ctime, crtime, atime, mtime,
6289  (short) 0, 0, 0, null, null, null, parentPath, null,
6290  extension);
6291 
6292  } catch (SQLException ex) {
6293  logger.log(Level.WARNING, "Failed to add file system file", ex);
6294  } finally {
6295  closeStatement(queryStatement);
6296  if (null != transaction) {
6297  try {
6298  transaction.rollback();
6299  } catch (TskCoreException ex2) {
6300  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6301  }
6302  }
6303  }
6304  return null;
6305  }
6306 
6315  public List<VirtualDirectory> getVirtualDirectoryRoots() throws TskCoreException {
6316  CaseDbConnection connection = connections.getConnection();
6318  Statement s = null;
6319  ResultSet rs = null;
6320  try {
6321  s = connection.createStatement();
6322  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE" //NON-NLS
6323  + " type = " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
6324  + " AND obj_id = data_source_obj_id"
6325  + " ORDER BY dir_type, LOWER(name)"); //NON-NLS
6326  List<VirtualDirectory> virtDirRootIds = new ArrayList<VirtualDirectory>();
6327  while (rs.next()) {
6328  virtDirRootIds.add(virtualDirectory(rs, connection));
6329  }
6330  return virtDirRootIds;
6331  } catch (SQLException ex) {
6332  throw new TskCoreException("Error getting local files virtual folder id", ex);
6333  } finally {
6334  closeResultSet(rs);
6335  closeStatement(s);
6336  connection.close();
6338  }
6339  }
6340 
6353  public final List<LayoutFile> addLayoutFiles(Content parent, List<TskFileRange> fileRanges) throws TskCoreException {
6354  assert (null != fileRanges);
6355  if (null == fileRanges) {
6356  throw new TskCoreException("TskFileRange object is null");
6357  }
6358 
6359  assert (null != parent);
6360  if (null == parent) {
6361  throw new TskCoreException("Conent is null");
6362  }
6363 
6364  CaseDbTransaction transaction = null;
6365  Statement statement = null;
6366  ResultSet resultSet = null;
6367 
6368  try {
6369  transaction = beginTransaction();
6370  CaseDbConnection connection = transaction.getConnection();
6371 
6372  List<LayoutFile> fileRangeLayoutFiles = new ArrayList<LayoutFile>();
6373  for (TskFileRange fileRange : fileRanges) {
6374  /*
6375  * Insert a row for the Tsk file range into the tsk_objects
6376  * table: INSERT INTO tsk_objects (par_obj_id, type) VALUES (?,
6377  * ?)
6378  */
6379  long fileRangeId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6380  long end_byte_in_parent = fileRange.getByteStart() + fileRange.getByteLen() - 1;
6381  /*
6382  * Insert a row for the Tsk file range into the tsk_files table:
6383  * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type,
6384  * has_path, dir_type, meta_type, dir_flags, meta_flags, size,
6385  * ctime, crtime, atime, mtime, md5, known, mime_type,
6386  * parent_path, data_source_obj_id,extension) VALUES (?, ?, ?,
6387  * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6388  */
6389  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6390  prepStmt.clearParameters();
6391  prepStmt.setLong(1, fileRangeId); // obj_id from tsk_objects
6392  prepStmt.setNull(2, java.sql.Types.BIGINT); // fs_obj_id
6393  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]
6394  prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()); // type
6395  prepStmt.setNull(5, java.sql.Types.BIGINT); // has_path
6396  prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
6397  prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
6398  prepStmt.setShort(8, TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()); // dir_flags
6399  prepStmt.setShort(9, TSK_FS_META_FLAG_ENUM.UNALLOC.getValue()); // nmeta_flags
6400  prepStmt.setLong(10, fileRange.getByteLen()); // size
6401  prepStmt.setNull(11, java.sql.Types.BIGINT); // ctime
6402  prepStmt.setNull(12, java.sql.Types.BIGINT); // crtime
6403  prepStmt.setNull(13, java.sql.Types.BIGINT); // atime
6404  prepStmt.setNull(14, java.sql.Types.BIGINT); // mtime
6405  prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
6406  prepStmt.setNull(16, java.sql.Types.VARCHAR); // SHA-256
6407  prepStmt.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6408  prepStmt.setNull(18, java.sql.Types.VARCHAR); // MIME type
6409  prepStmt.setNull(19, java.sql.Types.VARCHAR); // parent path
6410  prepStmt.setLong(20, parent.getId()); // data_source_obj_id
6411 
6412  //extension, since this is not a FS file we just set it to null
6413  prepStmt.setString(21, null);
6414  connection.executeUpdate(prepStmt);
6415 
6416  /*
6417  * Insert a row in the tsk_layout_file table for each chunk of
6418  * the carved file. INSERT INTO tsk_file_layout (obj_id,
6419  * byte_start, byte_len, sequence) VALUES (?, ?, ?, ?)
6420  */
6421  prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
6422  prepStmt.clearParameters();
6423  prepStmt.setLong(1, fileRangeId); // obj_id
6424  prepStmt.setLong(2, fileRange.getByteStart()); // byte_start
6425  prepStmt.setLong(3, fileRange.getByteLen()); // byte_len
6426  prepStmt.setLong(4, fileRange.getSequence()); // sequence
6427  connection.executeUpdate(prepStmt);
6428 
6429  /*
6430  * Create a layout file representation of the carved file.
6431  */
6432  fileRangeLayoutFiles.add(new LayoutFile(this,
6433  fileRangeId,
6434  parent.getId(),
6435  Long.toString(fileRange.getSequence()),
6440  TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
6441  fileRange.getByteLen(),
6442  0L, 0L, 0L, 0L,
6443  null, null,
6445  parent.getUniquePath(),
6446  null));
6447  }
6448 
6449  transaction.commit();
6450  transaction = null;
6451  return fileRangeLayoutFiles;
6452 
6453  } catch (SQLException ex) {
6454  throw new TskCoreException("Failed to add layout files to case database", ex);
6455  } finally {
6456  closeResultSet(resultSet);
6457  closeStatement(statement);
6458 
6459  if (null != transaction) {
6460  try {
6461  transaction.rollback();
6462  } catch (TskCoreException ex2) {
6463  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6464  }
6465  }
6466  }
6467  }
6468 
6480  public final List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws TskCoreException {
6481  assert (null != carvingResult);
6482  if (null == carvingResult) {
6483  throw new TskCoreException("Carving is null");
6484  }
6485  assert (null != carvingResult.getParent());
6486  if (null == carvingResult.getParent()) {
6487  throw new TskCoreException("Carving result has null parent");
6488  }
6489  assert (null != carvingResult.getCarvedFiles());
6490  if (null == carvingResult.getCarvedFiles()) {
6491  throw new TskCoreException("Carving result has null carved files");
6492  }
6493  CaseDbTransaction transaction = null;
6494  Statement statement = null;
6495  ResultSet resultSet = null;
6496  long newCacheKey = 0; // Used to roll back cache if transaction is rolled back.
6497  try {
6498  transaction = beginTransaction();
6499  CaseDbConnection connection = transaction.getConnection();
6500 
6501  /*
6502  * Carved files are "re-parented" as children of the $CarvedFiles
6503  * virtual directory of the root file system, volume, or image
6504  * ancestor of the carved files parent, but if no such ancestor is
6505  * found, then the parent specified in the carving result is used.
6506  */
6507  Content root = carvingResult.getParent();
6508  while (null != root) {
6509  if (root instanceof FileSystem || root instanceof Volume || root instanceof Image) {
6510  break;
6511  }
6512  root = root.getParent();
6513  }
6514  if (null == root) {
6515  root = carvingResult.getParent();
6516  }
6517 
6518  /*
6519  * Get or create the $CarvedFiles virtual directory for the root
6520  * ancestor.
6521  */
6522  VirtualDirectory carvedFilesDir = rootIdsToCarvedFileDirs.get(root.getId());
6523  if (null == carvedFilesDir) {
6524  List<Content> rootChildren;
6525  if (root instanceof FileSystem) {
6526  rootChildren = ((FileSystem) root).getRootDirectory().getChildren();
6527  } else {
6528  rootChildren = root.getChildren();
6529  }
6530  for (Content child : rootChildren) {
6531  if (child instanceof VirtualDirectory && child.getName().equals(VirtualDirectory.NAME_CARVED)) {
6532  carvedFilesDir = (VirtualDirectory) child;
6533  break;
6534  }
6535  }
6536  if (null == carvedFilesDir) {
6537  long parId = root.getId();
6538  // $CarvedFiles should be a child of the root directory, not the file system
6539  if (root instanceof FileSystem) {
6540  Content rootDir = ((FileSystem) root).getRootDirectory();
6541  parId = rootDir.getId();
6542  }
6543  carvedFilesDir = addVirtualDirectory(parId, VirtualDirectory.NAME_CARVED, transaction);
6544  }
6545  newCacheKey = root.getId();
6546  rootIdsToCarvedFileDirs.put(newCacheKey, carvedFilesDir);
6547  }
6548 
6549  /*
6550  * Add the carved files to the database as children of the
6551  * $CarvedFile directory of the root ancestor.
6552  */
6553  String parentPath = getFileParentPath(carvedFilesDir.getId(), connection) + carvedFilesDir.getName() + "/";
6554  List<LayoutFile> carvedFiles = new ArrayList<LayoutFile>();
6555  for (CarvingResult.CarvedFile carvedFile : carvingResult.getCarvedFiles()) {
6556  /*
6557  * Insert a row for the carved file into the tsk_objects table:
6558  * INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6559  */
6560  long carvedFileId = addObject(carvedFilesDir.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6561 
6562  /*
6563  * Insert a row for the carved file into the tsk_files table:
6564  * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type,
6565  * has_path, dir_type, meta_type, dir_flags, meta_flags, size,
6566  * ctime, crtime, atime, mtime, md5, known, mime_type,
6567  * parent_path, data_source_obj_id,extenion) VALUES (?, ?, ?, ?,
6568  * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6569  */
6570  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6571  prepStmt.clearParameters();
6572  prepStmt.setLong(1, carvedFileId); // obj_id
6573  if (root instanceof FileSystem) {
6574  prepStmt.setLong(2, root.getId()); // fs_obj_id
6575  } else {
6576  prepStmt.setNull(2, java.sql.Types.BIGINT); // fs_obj_id
6577  }
6578  prepStmt.setString(3, carvedFile.getName()); // name
6579  prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()); // type
6580  prepStmt.setShort(5, (short) 1); // has_path
6581  prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
6582  prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
6583  prepStmt.setShort(8, TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()); // dir_flags
6584  prepStmt.setShort(9, TSK_FS_META_FLAG_ENUM.UNALLOC.getValue()); // nmeta_flags
6585  prepStmt.setLong(10, carvedFile.getSizeInBytes()); // size
6586  prepStmt.setNull(11, java.sql.Types.BIGINT); // ctime
6587  prepStmt.setNull(12, java.sql.Types.BIGINT); // crtime
6588  prepStmt.setNull(13, java.sql.Types.BIGINT); // atime
6589  prepStmt.setNull(14, java.sql.Types.BIGINT); // mtime
6590  prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
6591  prepStmt.setNull(16, java.sql.Types.VARCHAR); // SHA-256
6592  prepStmt.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6593  prepStmt.setNull(18, java.sql.Types.VARCHAR); // MIME type
6594  prepStmt.setString(19, parentPath); // parent path
6595  prepStmt.setLong(20, carvedFilesDir.getDataSourceObjectId()); // data_source_obj_id
6596  prepStmt.setString(21, extractExtension(carvedFile.getName())); //extension
6597  connection.executeUpdate(prepStmt);
6598 
6599  /*
6600  * Insert a row in the tsk_layout_file table for each chunk of
6601  * the carved file. INSERT INTO tsk_file_layout (obj_id,
6602  * byte_start, byte_len, sequence) VALUES (?, ?, ?, ?)
6603  */
6604  prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
6605  for (TskFileRange tskFileRange : carvedFile.getLayoutInParent()) {
6606  prepStmt.clearParameters();
6607  prepStmt.setLong(1, carvedFileId); // obj_id
6608  prepStmt.setLong(2, tskFileRange.getByteStart()); // byte_start
6609  prepStmt.setLong(3, tskFileRange.getByteLen()); // byte_len
6610  prepStmt.setLong(4, tskFileRange.getSequence()); // sequence
6611  connection.executeUpdate(prepStmt);
6612  }
6613 
6614  /*
6615  * Create a layout file representation of the carved file.
6616  */
6617  carvedFiles.add(new LayoutFile(this,
6618  carvedFileId,
6619  carvedFilesDir.getDataSourceObjectId(),
6620  carvedFile.getName(),
6625  TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
6626  carvedFile.getSizeInBytes(),
6627  0L, 0L, 0L, 0L,
6628  null, null,
6630  parentPath,
6631  null));
6632  }
6633 
6634  transaction.commit();
6635  transaction = null;
6636  return carvedFiles;
6637 
6638  } catch (SQLException ex) {
6639  throw new TskCoreException("Failed to add carved files to case database", ex);
6640  } finally {
6641  closeResultSet(resultSet);
6642  closeStatement(statement);
6643 
6644  if (null != transaction) {
6645  try {
6646  transaction.rollback();
6647  } catch (TskCoreException ex2) {
6648  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6649  }
6650  if (0 != newCacheKey) {
6651  rootIdsToCarvedFileDirs.remove(newCacheKey);
6652  }
6653  }
6654  }
6655  }
6656 
6687  public DerivedFile addDerivedFile(String fileName, String localPath,
6688  long size, long ctime, long crtime, long atime, long mtime,
6689  boolean isFile, Content parentObj,
6690  String rederiveDetails, String toolName, String toolVersion,
6691  String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
6692  // Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
6693  localPath = localPath.replaceAll("^[/\\\\]+", "");
6694 
6695  TimelineManager timelineManager = getTimelineManager();
6696 
6697  CaseDbTransaction transaction = beginTransaction();
6698  CaseDbConnection connection = transaction.getConnection();
6699  try {
6700  final long parentId = parentObj.getId();
6701  String parentPath = "";
6702  if (parentObj instanceof BlackboardArtifact) {
6703  parentPath = parentObj.getUniquePath() + '/' + parentObj.getName() + '/';
6704  } else if (parentObj instanceof AbstractFile) {
6705  parentPath = ((AbstractFile) parentObj).getParentPath() + parentObj.getName() + '/'; //NON-NLS
6706  }
6707 
6708  // Insert a row for the derived file into the tsk_objects table.
6709  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6710  long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6711 
6712  // Insert a row for the virtual directory into the tsk_files table.
6713  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
6714  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type,
6715  // parent_path, data_source_obj_id, extension)
6716  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
6717  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6718  statement.clearParameters();
6719  statement.setLong(1, newObjId);
6720 
6721  // If the parentFile is part of a file system, use its file system object ID.
6722  long fsObjId = this.getFileSystemId(parentId, connection);
6723  if (fsObjId != -1) {
6724  statement.setLong(2, fsObjId);
6725  } else {
6726  statement.setNull(2, java.sql.Types.BIGINT);
6727  }
6728  statement.setString(3, fileName);
6729 
6730  //type, has_path
6731  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType());
6732  statement.setShort(5, (short) 1);
6733 
6734  //flags
6736  statement.setShort(6, dirType.getValue());
6738  statement.setShort(7, metaType.getValue());
6739 
6740  //note: using alloc under assumption that derived files derive from alloc files
6742  statement.setShort(8, dirFlag.getValue());
6743  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
6744  | TSK_FS_META_FLAG_ENUM.USED.getValue());
6745  statement.setShort(9, metaFlags);
6746 
6747  //size
6748  //prevent negative size
6749  long savedSize = size < 0 ? 0 : size;
6750  statement.setLong(10, savedSize);
6751 
6752  //mactimes
6753  //long ctime, long crtime, long atime, long mtime,
6754  statement.setLong(11, ctime);
6755  statement.setLong(12, crtime);
6756  statement.setLong(13, atime);
6757  statement.setLong(14, mtime);
6758 
6759  statement.setNull(15, java.sql.Types.VARCHAR); // MD5
6760  statement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
6761  statement.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6762  statement.setNull(18, java.sql.Types.VARCHAR); // MIME type
6763 
6764  //parent path
6765  statement.setString(19, parentPath);
6766 
6767  // root data source object id
6768  long dataSourceObjId = getDataSourceObjectId(connection, parentId);
6769  statement.setLong(20, dataSourceObjId);
6770  final String extension = extractExtension(fileName);
6771  //extension
6772  statement.setString(21, extension);
6773 
6774  connection.executeUpdate(statement);
6775 
6776  //add localPath
6777  addFilePath(connection, newObjId, localPath, encodingType);
6778 
6779  DerivedFile derivedFile = new DerivedFile(this, newObjId, dataSourceObjId, fileName, dirType, metaType, dirFlag, metaFlags,
6780  savedSize, ctime, crtime, atime, mtime, null, null, null, parentPath, localPath, parentId, null, encodingType, extension);
6781 
6782  timelineManager.addEventsForNewFile(derivedFile, connection);
6783  transaction.commit();
6784  //TODO add derived method to tsk_files_derived and tsk_files_derived_method
6785  return derivedFile;
6786  } catch (SQLException ex) {
6787  connection.rollbackTransaction();
6788  throw new TskCoreException("Failed to add derived file to case database", ex);
6789  } finally {
6790  connection.close();
6791  }
6792  }
6793 
6824  public DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath,
6825  long size, long ctime, long crtime, long atime, long mtime,
6826  boolean isFile, String mimeType,
6827  String rederiveDetails, String toolName, String toolVersion,
6828  String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
6829 
6830  // Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
6831  localPath = localPath.replaceAll("^[/\\\\]+", "");
6832 
6833  CaseDbConnection connection = connections.getConnection();
6835  ResultSet rs = null;
6836  try {
6837  Content parentObj = derivedFile.getParent();
6838  connection.beginTransaction();
6839  final long parentId = parentObj.getId();
6840  String parentPath = "";
6841  if (parentObj instanceof BlackboardArtifact) {
6842  parentPath = parentObj.getUniquePath() + '/' + parentObj.getName() + '/';
6843  } else if (parentObj instanceof AbstractFile) {
6844  parentPath = ((AbstractFile) parentObj).getParentPath() + parentObj.getName() + '/'; //NON-NLS
6845  }
6846  // UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, "
6847  // + "size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? WHERE obj_id = ?"), //NON-NLS
6848  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_DERIVED_FILE);
6849  statement.clearParameters();
6850 
6851  //type
6852  statement.setShort(1, TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType());
6853 
6854  //flags
6856  statement.setShort(2, dirType.getValue());
6858  statement.setShort(3, metaType.getValue());
6859 
6860  //note: using alloc under assumption that derived files derive from alloc files
6862  statement.setShort(4, dirFlag.getValue());
6863  final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
6864  | TSK_FS_META_FLAG_ENUM.USED.getValue());
6865  statement.setShort(5, metaFlags);
6866 
6867  //size
6868  //prevent negative size
6869  long savedSize = size < 0 ? 0 : size;
6870  statement.setLong(6, savedSize);
6871 
6872  //mactimes
6873  //long ctime, long crtime, long atime, long mtime,
6874  statement.setLong(7, ctime);
6875  statement.setLong(8, crtime);
6876  statement.setLong(9, atime);
6877  statement.setLong(10, mtime);
6878  statement.setString(11, mimeType);
6879  statement.setString(12, String.valueOf(derivedFile.getId()));
6880  connection.executeUpdate(statement);
6881 
6882  //add localPath
6883  updateFilePath(connection, derivedFile.getId(), localPath, encodingType);
6884 
6885  connection.commitTransaction();
6886 
6887  long dataSourceObjId = getDataSourceObjectId(connection, parentId);
6888  final String extension = extractExtension(derivedFile.getName());
6889  return new DerivedFile(this, derivedFile.getId(), dataSourceObjId, derivedFile.getName(), dirType, metaType, dirFlag, metaFlags,
6890  savedSize, ctime, crtime, atime, mtime, null, null, null, parentPath, localPath, parentId, null, encodingType, extension);
6891  } catch (SQLException ex) {
6892  connection.rollbackTransaction();
6893  throw new TskCoreException("Failed to add derived file to case database", ex);
6894  } finally {
6895  closeResultSet(rs);
6896  connection.close();
6898  }
6899  }
6900 
6920  public LocalFile addLocalFile(String fileName, String localPath,
6921  long size, long ctime, long crtime, long atime, long mtime,
6922  boolean isFile, TskData.EncodingType encodingType,
6923  AbstractFile parent) throws TskCoreException {
6924 
6925  CaseDbTransaction localTrans = beginTransaction();
6926  try {
6927  LocalFile created = addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile, encodingType, parent, localTrans);
6928  localTrans.commit();
6929  localTrans = null;
6930  return created;
6931  } finally {
6932  if (null != localTrans) {
6933  try {
6934  localTrans.rollback();
6935  } catch (TskCoreException ex2) {
6936  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6937  }
6938  }
6939  }
6940  }
6941 
6966  public LocalFile addLocalFile(String fileName, String localPath,
6967  long size, long ctime, long crtime, long atime, long mtime,
6968  boolean isFile, TskData.EncodingType encodingType,
6969  Content parent, CaseDbTransaction transaction) throws TskCoreException {
6970 
6971  return addLocalFile(fileName, localPath,
6972  size, ctime, crtime, atime, mtime,
6973  null, null, null,
6974  isFile, encodingType,
6975  parent, transaction);
6976  }
6977 
7005  public LocalFile addLocalFile(String fileName, String localPath,
7006  long size, long ctime, long crtime, long atime, long mtime,
7007  String md5, String sha256, FileKnown known, String mimeType,
7008  boolean isFile, TskData.EncodingType encodingType,
7009  Content parent, CaseDbTransaction transaction) throws TskCoreException {
7010  CaseDbConnection connection = transaction.getConnection();
7011  Statement queryStatement = null;
7012  try {
7013 
7014  // Insert a row for the local/logical file into the tsk_objects table.
7015  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
7016  long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
7017 
7018  // Insert a row for the local/logical file into the tsk_files table.
7019  // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
7020  // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type,
7021  // parent_path, data_source_obj_id,extension)
7022  // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
7023  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
7024  statement.clearParameters();
7025  statement.setLong(1, objectId);
7026  statement.setNull(2, java.sql.Types.BIGINT); // Not part of a file system
7027  statement.setString(3, fileName);
7028  statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType());
7029  statement.setShort(5, (short) 1);
7031  statement.setShort(6, dirType.getValue());
7033  statement.setShort(7, metaType.getValue());
7035  statement.setShort(8, dirFlag.getValue());
7036  short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue() | TSK_FS_META_FLAG_ENUM.USED.getValue());
7037  statement.setShort(9, metaFlags);
7038  //prevent negative size
7039  long savedSize = size < 0 ? 0 : size;
7040  statement.setLong(10, savedSize);
7041  statement.setLong(11, ctime);
7042  statement.setLong(12, crtime);
7043  statement.setLong(13, atime);
7044  statement.setLong(14, mtime);
7045  statement.setString(15, md5);
7046  statement.setString(16, sha256);
7047  if (known != null) {
7048  statement.setByte(17, known.getFileKnownValue());
7049  } else {
7050  statement.setByte(17, FileKnown.UNKNOWN.getFileKnownValue());
7051  }
7052  statement.setString(18, mimeType);
7053  String parentPath;
7054  long dataSourceObjId;
7055 
7056  if (parent instanceof AbstractFile) {
7057  AbstractFile parentFile = (AbstractFile) parent;
7058  if (isRootDirectory(parentFile, transaction)) {
7059  parentPath = "/";
7060  } else {
7061  parentPath = parentFile.getParentPath() + parent.getName() + "/"; //NON-NLS
7062  }
7063  dataSourceObjId = parentFile.getDataSourceObjectId();
7064  } else {
7065  parentPath = "/";
7066  dataSourceObjId = getDataSourceObjectId(connection, parent.getId());
7067  }
7068  statement.setString(19, parentPath);
7069  statement.setLong(20, dataSourceObjId);
7070  final String extension = extractExtension(fileName);
7071  statement.setString(21, extension);
7072 
7073  connection.executeUpdate(statement);
7074  addFilePath(connection, objectId, localPath, encodingType);
7075  LocalFile localFile = new LocalFile(this,
7076  objectId,
7077  fileName,
7079  dirType,
7080  metaType,
7081  dirFlag,
7082  metaFlags,
7083  savedSize,
7084  ctime, crtime, atime, mtime,
7085  mimeType, md5, sha256, known,
7086  parent.getId(), parentPath,
7087  dataSourceObjId,
7088  localPath,
7089  encodingType, extension);
7090  getTimelineManager().addEventsForNewFile(localFile, connection);
7091  return localFile;
7092 
7093  } catch (SQLException ex) {
7094  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);
7095  } finally {
7096  closeStatement(queryStatement);
7097  }
7098  }
7099 
7112  private boolean isRootDirectory(AbstractFile file, CaseDbTransaction transaction) throws TskCoreException {
7113  CaseDbConnection connection = transaction.getConnection();
7114  Statement statement = null;
7115  ResultSet resultSet = null;
7116 
7117  try {
7118  String query = String.format("SELECT ParentRow.type AS parent_type, ParentRow.obj_id AS parent_object_id "
7119  + "FROM tsk_objects ParentRow JOIN tsk_objects ChildRow ON ChildRow.par_obj_id = ParentRow.obj_id "
7120  + "WHERE ChildRow.obj_id = %s;", file.getId());
7121 
7122  statement = connection.createStatement();
7123  resultSet = statement.executeQuery(query);
7124  if (resultSet.next()) {
7125  long parentId = resultSet.getLong("parent_object_id");
7126  if (parentId == 0) {
7127  return true;
7128  }
7129  int type = resultSet.getInt("parent_type");
7130  return (type == TskData.ObjectType.IMG.getObjectType()
7131  || type == TskData.ObjectType.VS.getObjectType()
7132  || type == TskData.ObjectType.VOL.getObjectType()
7133  || type == TskData.ObjectType.FS.getObjectType());
7134 
7135  } else {
7136  return true; // The file has no parent
7137  }
7138  } catch (SQLException ex) {
7139  throw new TskCoreException(String.format("Failed to lookup parent of file (%s) with id %d", file.getName(), file.getId()), ex);
7140  } finally {
7141  closeResultSet(resultSet);
7142  closeStatement(statement);
7143  }
7144  }
7145 
7165  public LayoutFile addLayoutFile(String fileName,
7166  long size,
7167  TSK_FS_NAME_FLAG_ENUM dirFlag, TSK_FS_META_FLAG_ENUM metaFlag,
7168  long ctime, long crtime, long atime, long mtime,
7169  List<TskFileRange> fileRanges,
7170  Content parent) throws TskCoreException {
7171 
7172  if (null == parent) {
7173  throw new TskCoreException("Parent can not be null");
7174  }
7175 
7176  String parentPath;
7177  if (parent instanceof AbstractFile) {
7178  parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + '/'; //NON-NLS
7179  } else {
7180  parentPath = "/";
7181  }
7182 
7183  CaseDbTransaction transaction = null;
7184  Statement statement = null;
7185  ResultSet resultSet = null;
7186  try {
7187  transaction = beginTransaction();
7188  CaseDbConnection connection = transaction.getConnection();
7189 
7190  /*
7191  * Insert a row for the layout file into the tsk_objects table:
7192  * INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
7193  */
7194  long newFileId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
7195 
7196  /*
7197  * Insert a row for the file into the tsk_files table: INSERT INTO
7198  * tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type,
7199  * meta_type, dir_flags, meta_flags, size, ctime, crtime, atime,
7200  * mtime, md5, known, mime_type, parent_path,
7201  * data_source_obj_id,extenion) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,
7202  * ?, ?, ?, ?, ?, ?, ?,?)
7203  */
7204  PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
7205  prepStmt.clearParameters();
7206  prepStmt.setLong(1, newFileId); // obj_id
7207 
7208  // If the parent is part of a file system, grab its file system ID
7209  if (0 != parent.getId()) {
7210  long parentFs = this.getFileSystemId(parent.getId(), connection);
7211  if (parentFs != -1) {
7212  prepStmt.setLong(2, parentFs);
7213  } else {
7214  prepStmt.setNull(2, java.sql.Types.BIGINT);
7215  }
7216  } else {
7217  prepStmt.setNull(2, java.sql.Types.BIGINT);
7218  }
7219  prepStmt.setString(3, fileName); // name
7220  prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType()); // type
7221  prepStmt.setShort(5, (short) 0); // has_path
7222  prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
7223  prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
7224  prepStmt.setShort(8, dirFlag.getValue()); // dir_flags
7225  prepStmt.setShort(9, metaFlag.getValue()); // meta_flags
7226  //prevent negative size
7227  long savedSize = size < 0 ? 0 : size;
7228  prepStmt.setLong(10, savedSize); // size
7229  prepStmt.setLong(11, ctime); // ctime
7230  prepStmt.setLong(12, crtime); // crtime
7231  prepStmt.setLong(13, atime); // atime
7232  prepStmt.setLong(14, mtime); // mtime
7233  prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
7234  prepStmt.setNull(16, java.sql.Types.VARCHAR); // SHA-256
7235  prepStmt.setByte(17, FileKnown.UNKNOWN.getFileKnownValue()); // Known
7236  prepStmt.setNull(18, java.sql.Types.VARCHAR); // MIME type
7237  prepStmt.setString(19, parentPath); // parent path
7238  prepStmt.setLong(20, parent.getDataSource().getId()); // data_source_obj_id
7239 
7240  prepStmt.setString(21, extractExtension(fileName)); //extension
7241  connection.executeUpdate(prepStmt);
7242 
7243  /*
7244  * Insert a row in the tsk_layout_file table for each chunk of the
7245  * carved file. INSERT INTO tsk_file_layout (obj_id, byte_start,
7246  * byte_len, sequence) VALUES (?, ?, ?, ?)
7247  */
7248  prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
7249  for (TskFileRange tskFileRange : fileRanges) {
7250  prepStmt.clearParameters();
7251  prepStmt.setLong(1, newFileId); // obj_id
7252  prepStmt.setLong(2, tskFileRange.getByteStart()); // byte_start
7253  prepStmt.setLong(3, tskFileRange.getByteLen()); // byte_len
7254  prepStmt.setLong(4, tskFileRange.getSequence()); // sequence
7255  connection.executeUpdate(prepStmt);
7256  }
7257 
7258  /*
7259  * Create a layout file representation of the carved file.
7260  */
7261  LayoutFile layoutFile = new LayoutFile(this,
7262  newFileId,
7263  parent.getDataSource().getId(),
7264  fileName,
7268  dirFlag,
7269  metaFlag.getValue(),
7270  savedSize,
7271  ctime, crtime, atime, mtime,
7272  null, null,
7274  parentPath,
7275  null);
7276 
7277  transaction.commit();
7278  transaction = null;
7279  return layoutFile;
7280 
7281  } catch (SQLException ex) {
7282  throw new TskCoreException("Failed to add layout file " + fileName + " to case database", ex);
7283  } finally {
7284  closeResultSet(resultSet);
7285  closeStatement(statement);
7286 
7287  if (null != transaction) {
7288  try {
7289  transaction.rollback();
7290  } catch (TskCoreException ex2) {
7291  logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
7292  }
7293  }
7294  }
7295  }
7296 
7309  private long getDataSourceObjectId(CaseDbConnection connection, long objectId) throws TskCoreException {
7311  Statement statement = null;
7312  ResultSet resultSet = null;
7313  try {
7314  statement = connection.createStatement();
7315  long dataSourceObjId;
7316  long ancestorId = objectId;
7317  do {
7318  dataSourceObjId = ancestorId;
7319  String query = String.format("SELECT par_obj_id FROM tsk_objects WHERE obj_id = %s;", ancestorId);
7320  resultSet = statement.executeQuery(query);
7321  if (resultSet.next()) {
7322  ancestorId = resultSet.getLong("par_obj_id");
7323  } else {
7324  throw new TskCoreException(String.format("tsk_objects table is corrupt, SQL query returned no result: %s", query));
7325  }
7326  resultSet.close();
7327  resultSet = null;
7328  } while (0 != ancestorId); // Not NULL
7329  return dataSourceObjId;
7330  } catch (SQLException ex) {
7331  throw new TskCoreException(String.format("Error finding root data source for object (obj_id = %d)", objectId), ex);
7332  } finally {
7333  closeResultSet(resultSet);
7334  closeStatement(statement);
7336  }
7337  }
7338 
7350  private void addFilePath(CaseDbConnection connection, long objId, String path, TskData.EncodingType type) throws SQLException {
7351  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LOCAL_PATH);
7352  statement.clearParameters();
7353  statement.setLong(1, objId);
7354  statement.setString(2, path);
7355  statement.setInt(3, type.getType());
7356  connection.executeUpdate(statement);
7357  }
7358 
7370  private void updateFilePath(CaseDbConnection connection, long objId, String path, TskData.EncodingType type) throws SQLException {
7371  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_LOCAL_PATH);
7372  statement.clearParameters();
7373  statement.setString(1, path);
7374  statement.setInt(2, type.getType());
7375  statement.setLong(3, objId);
7376  connection.executeUpdate(statement);
7377  }
7378 
7394  public List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException {
7395  return findFiles(dataSource, fileName, parentFile.getName());
7396  }
7397 
7409  public long countFilesWhere(String sqlWhereClause) throws TskCoreException {
7410  CaseDbConnection connection = connections.getConnection();
7412  Statement s = null;
7413  ResultSet rs = null;
7414  try {
7415  s = connection.createStatement();
7416  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
7417  rs.next();
7418  return rs.getLong("count");
7419  } catch (SQLException e) {
7420  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.countFilesWhere().", e);
7421  } finally {
7422  closeResultSet(rs);
7423  closeStatement(s);
7424  connection.close();
7426  }
7427  }
7428 
7446  public List<AbstractFile> findAllFilesWhere(String sqlWhereClause) throws TskCoreException {
7447  CaseDbConnection connection = connections.getConnection();
7449  Statement s = null;
7450  ResultSet rs = null;
7451  try {
7452  s = connection.createStatement();
7453  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
7454  return resultSetToAbstractFiles(rs, connection);
7455  } catch (SQLException e) {
7456  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFilesWhere(): " + sqlWhereClause, e);
7457  } finally {
7458  closeResultSet(rs);
7459  closeStatement(s);
7460  connection.close();
7462  }
7463  }
7464 
7483  public List<AbstractFile> findAllFilesInFolderWhere(long parentId, String sqlWhereClause) throws TskCoreException{
7484  String queryTemplate = "SELECT tsk_files.* FROM tsk_files JOIN tsk_objects ON tsk_objects.obj_id = tsk_files.obj_id WHERE par_obj_id = %d AND %s";
7485 
7486  try(CaseDbConnection connection = connections.getConnection()) {
7488 
7489  String query = String.format(queryTemplate, parentId, sqlWhereClause);
7490  try(Statement s = connection.createStatement(); ResultSet rs = connection.executeQuery(s, query)) {
7491  return resultSetToAbstractFiles(rs, connection);
7492  } catch(SQLException ex) {
7493  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFilesInFolderWhere(): " + query, ex);
7494  }
7495  }finally {
7497  }
7498  }
7499 
7512  public List<Long> findAllFileIdsWhere(String sqlWhereClause) throws TskCoreException {
7513  CaseDbConnection connection = connections.getConnection();
7515  Statement s = null;
7516  ResultSet rs = null;
7517  try {
7518  s = connection.createStatement();
7519  rs = connection.executeQuery(s, "SELECT obj_id FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
7520  List<Long> ret = new ArrayList<Long>();
7521  while (rs.next()) {
7522  ret.add(rs.getLong("obj_id"));
7523  }
7524  return ret;
7525  } catch (SQLException e) {
7526  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFileIdsWhere(): " + sqlWhereClause, e);
7527  } finally {
7528  closeResultSet(rs);
7529  closeStatement(s);
7530  connection.close();
7532  }
7533  }
7534 
7546  public List<AbstractFile> openFiles(Content dataSource, String filePath) throws TskCoreException {
7547 
7548  // get the non-unique path (strip of image and volume path segments, if
7549  // the exist.
7550  String path = AbstractFile.createNonUniquePath(filePath).toLowerCase();
7551 
7552  // split the file name from the parent path
7553  int lastSlash = path.lastIndexOf('/'); //NON-NLS
7554 
7555  // if the last slash is at the end, strip it off
7556  if (lastSlash == path.length()) {
7557  path = path.substring(0, lastSlash - 1);
7558  lastSlash = path.lastIndexOf('/'); //NON-NLS
7559  }
7560 
7561  String parentPath = path.substring(0, lastSlash);
7562  String fileName = path.substring(lastSlash);
7563 
7564  return findFiles(dataSource, fileName, parentPath);
7565  }
7566 
7577  public List<TskFileRange> getFileRanges(long id) throws TskCoreException {
7578  CaseDbConnection connection = connections.getConnection();
7580  Statement s = null;
7581  ResultSet rs = null;
7582  try {
7583  s = connection.createStatement();
7584  rs = connection.executeQuery(s, "SELECT * FROM tsk_file_layout WHERE obj_id = " + id + " ORDER BY sequence");
7585  List<TskFileRange> ranges = new ArrayList<TskFileRange>();
7586  while (rs.next()) {
7587  TskFileRange range = new TskFileRange(rs.getLong("byte_start"), //NON-NLS
7588  rs.getLong("byte_len"), rs.getLong("sequence")); //NON-NLS
7589  ranges.add(range);
7590  }
7591  return ranges;
7592  } catch (SQLException ex) {
7593  throw new TskCoreException("Error getting TskFileLayoutRanges by id, id = " + id, ex);
7594  } finally {
7595  closeResultSet(rs);
7596  closeStatement(s);
7597  connection.close();
7599  }
7600  }
7601 
7612  public Image getImageById(long id) throws TskCoreException {
7613  CaseDbConnection connection = connections.getConnection();
7615  Statement s = null;
7616  ResultSet rs = null;
7617  try {
7618  s = connection.createStatement();
7619  rs = connection.executeQuery(s, "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, tsk_image_names.name "
7620  + "FROM tsk_image_info "
7621  + "INNER JOIN data_source_info ON tsk_image_info.obj_id = data_source_info.obj_id "
7622  + "LEFT JOIN tsk_image_names ON tsk_image_names.obj_id = data_source_info.obj_id "
7623  + "WHERE tsk_image_info.obj_id = " + id); //NON-NLS
7624 
7625  List<String> imagePaths = new ArrayList<>();
7626  long type, ssize, size;
7627  String tzone, md5, sha1, sha256, name, device_id, imagePath;
7628 
7629  if (rs.next()) {
7630  imagePath = rs.getString("name");
7631  if (imagePath != null) {
7632  imagePaths.add(imagePath);
7633  }
7634  type = rs.getLong("type"); //NON-NLS
7635  ssize = rs.getLong("ssize"); //NON-NLS
7636  tzone = rs.getString("tzone"); //NON-NLS
7637  size = rs.getLong("size"); //NON-NLS
7638  md5 = rs.getString("md5"); //NON-NLS
7639  sha1 = rs.getString("sha1"); //NON-NLS
7640  sha256 = rs.getString("sha256"); //NON-NLS
7641  name = rs.getString("display_name");
7642  if (name == null) {
7643  if (imagePaths.size() > 0) {
7644  String path = imagePaths.get(0);
7645  name = (new java.io.File(path)).getName();
7646  } else {
7647  name = "";
7648  }
7649  }
7650  device_id = rs.getString("device_id");
7651  } else {
7652  throw new TskCoreException("No image found for id: " + id);
7653  }
7654 
7655  // image can have multiple paths, therefore there can be multiple rows in the result set
7656  while (rs.next()) {
7657  imagePath = rs.getString("name");
7658  if (imagePath != null) {
7659  imagePaths.add(imagePath);
7660  }
7661  }
7662 
7663  return new Image(this, id, type, device_id, ssize, name,
7664  imagePaths.toArray(new String[imagePaths.size()]), tzone, md5, sha1, sha256, size);
7665  } catch (SQLException ex) {
7666  throw new TskCoreException("Error getting Image by id, id = " + id, ex);
7667  } finally {
7668  closeResultSet(rs);
7669  closeStatement(s);
7670  connection.close();
7672  }
7673  }
7674 
7686  VolumeSystem getVolumeSystemById(long id, Content parent) throws TskCoreException {
7687  CaseDbConnection connection = connections.getConnection();
7689  Statement s = null;
7690  ResultSet rs = null;
7691  try {
7692  s = connection.createStatement();
7693  rs = connection.executeQuery(s, "SELECT * FROM tsk_vs_info " //NON-NLS
7694  + "where obj_id = " + id); //NON-NLS
7695  if (rs.next()) {
7696  long type = rs.getLong("vs_type"); //NON-NLS
7697  long imgOffset = rs.getLong("img_offset"); //NON-NLS
7698  long blockSize = rs.getLong("block_size"); //NON-NLS
7699  VolumeSystem vs = new VolumeSystem(this, id, "", type, imgOffset, blockSize);
7700  vs.setParent(parent);
7701  return vs;
7702  } else {
7703  throw new TskCoreException("No volume system found for id:" + id);
7704  }
7705  } catch (SQLException ex) {
7706  throw new TskCoreException("Error getting Volume System by ID.", ex);
7707  } finally {
7708  closeResultSet(rs);
7709  closeStatement(s);
7710  connection.close();
7712  }
7713  }
7714 
7723  VolumeSystem getVolumeSystemById(long id, long parentId) throws TskCoreException {
7724  VolumeSystem vs = getVolumeSystemById(id, null);
7725  vs.setParentId(parentId);
7726  return vs;
7727  }
7728 
7740  FileSystem getFileSystemById(long id, Image parent) throws TskCoreException {
7741  return getFileSystemByIdHelper(id, parent);
7742  }
7743 
7752  FileSystem getFileSystemById(long id, long parentId) throws TskCoreException {
7753  Volume vol = null;
7754  FileSystem fs = getFileSystemById(id, vol);
7755  fs.setParentId(parentId);
7756  return fs;
7757  }
7758 
7770  FileSystem getFileSystemById(long id, Volume parent) throws TskCoreException {
7771  return getFileSystemByIdHelper(id, parent);
7772  }
7773 
7785  Pool getPoolById(long id, Content parent) throws TskCoreException {
7786  return getPoolByIdHelper(id, parent);
7787  }
7788 
7797  Pool getPoolById(long id, long parentId) throws TskCoreException {
7798  Pool pool = getPoolById(id, null);
7799  pool.setParentId(parentId);
7800  return pool;
7801  }
7802 
7814  private Pool getPoolByIdHelper(long id, Content parent) throws TskCoreException {
7815 
7817  try (CaseDbConnection connection = connections.getConnection();
7818  Statement s = connection.createStatement();
7819  ResultSet rs = connection.executeQuery(s, "SELECT * FROM tsk_pool_info " //NON-NLS
7820  + "where obj_id = " + id);) { //NON-NLS
7821  if (rs.next()) {
7822  Pool pool = new Pool(this, rs.getLong("obj_id"), TskData.TSK_POOL_TYPE_ENUM.valueOf(rs.getLong("pool_type")).getName(), rs.getLong("pool_type"));
7823  pool.setParent(parent);
7824 
7825  return pool;
7826  } else {
7827  throw new TskCoreException("No pool found for ID:" + id);
7828  }
7829  } catch (SQLException ex) {
7830  throw new TskCoreException("Error getting Pool by ID", ex);
7831  } finally {
7833  }
7834  }
7835 
7847  private FileSystem getFileSystemByIdHelper(long id, Content parent) throws TskCoreException {
7848  // see if we already have it
7849  // @@@ NOTE: this is currently kind of bad in that we are ignoring the parent value,
7850  // but it should be the same...
7851  synchronized (fileSystemIdMap) {
7852  if (fileSystemIdMap.containsKey(id)) {
7853  return fileSystemIdMap.get(id);
7854  }
7855  }
7856  CaseDbConnection connection = connections.getConnection();
7858  Statement s = null;
7859  ResultSet rs = null;
7860  try {
7861  s = connection.createStatement();
7862  rs = connection.executeQuery(s, "SELECT * FROM tsk_fs_info " //NON-NLS
7863  + "where obj_id = " + id); //NON-NLS
7864  if (rs.next()) {
7865  TskData.TSK_FS_TYPE_ENUM fsType = TskData.TSK_FS_TYPE_ENUM.valueOf(rs.getInt("fs_type")); //NON-NLS
7866  FileSystem fs = new FileSystem(this, rs.getLong("obj_id"), "", rs.getLong("img_offset"), //NON-NLS
7867  fsType, rs.getLong("block_size"), rs.getLong("block_count"), //NON-NLS
7868  rs.getLong("root_inum"), rs.getLong("first_inum"), rs.getLong("last_inum")); //NON-NLS
7869  fs.setParent(parent);
7870  // save it for the next call
7871  synchronized (fileSystemIdMap) {
7872  fileSystemIdMap.put(id, fs);
7873  }
7874  return fs;
7875  } else {
7876  throw new TskCoreException("No file system found for id:" + id);
7877  }
7878  } catch (SQLException ex) {
7879  throw new TskCoreException("Error getting File System by ID", ex);
7880  } finally {
7881  closeResultSet(rs);
7882  closeStatement(s);
7883  connection.close();
7885  }
7886  }
7887 
7899  Volume getVolumeById(long id, VolumeSystem parent) throws TskCoreException {
7900  CaseDbConnection connection = connections.getConnection();
7902  Statement s = null;
7903  ResultSet rs = null;
7904  try {
7905  s = connection.createStatement();
7906  rs = connection.executeQuery(s, "SELECT * FROM tsk_vs_parts " //NON-NLS
7907  + "where obj_id = " + id); //NON-NLS
7908  if (rs.next()) {
7916  String description;
7917  try {
7918  description = rs.getString("desc");
7919  } catch (Exception ex) {
7920  description = rs.getString("descr");
7921  }
7922  Volume vol = new Volume(this, rs.getLong("obj_id"), rs.getLong("addr"), //NON-NLS
7923  rs.getLong("start"), rs.getLong("length"), rs.getLong("flags"), //NON-NLS
7924  description);
7925  vol.setParent(parent);
7926  return vol;
7927  } else {
7928  throw new TskCoreException("No volume found for id:" + id);
7929  }
7930  } catch (SQLException ex) {
7931  throw new TskCoreException("Error getting Volume by ID", ex);
7932  } finally {
7933  closeResultSet(rs);
7934  closeStatement(s);
7935  connection.close();
7937  }
7938  }
7939 
7948  Volume getVolumeById(long id, long parentId) throws TskCoreException {
7949  Volume vol = getVolumeById(id, null);
7950  vol.setParentId(parentId);
7951  return vol;
7952  }
7953 
7965  Directory getDirectoryById(long id, FileSystem parentFs) throws TskCoreException {
7966  CaseDbConnection connection = connections.getConnection();
7968  Statement s = null;
7969  ResultSet rs = null;
7970  try {
7971  s = connection.createStatement();
7972  rs = connection.executeQuery(s, "SELECT * FROM tsk_files " //NON-NLS
7973  + "WHERE obj_id = " + id);
7974  Directory temp = null; //NON-NLS
7975  if (rs.next()) {
7976  final short type = rs.getShort("type"); //NON-NLS
7977  if (type == TSK_DB_FILES_TYPE_ENUM.FS.getFileType()) {
7978  if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
7979  || rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()) { //NON-NLS
7980  temp = directory(rs, parentFs);
7981  }
7982  } else if (type == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()) {
7983  throw new TskCoreException("Expecting an FS-type directory, got virtual, id: " + id);
7984  }
7985  } else {
7986  throw new TskCoreException("No Directory found for id:" + id);
7987  }
7988  return temp;
7989  } catch (SQLException ex) {
7990  throw new TskCoreException("Error getting Directory by ID", ex);
7991  } finally {
7992  closeResultSet(rs);
7993  closeStatement(s);
7994  connection.close();
7996  }
7997  }
7998 
8008  public Collection<FileSystem> getImageFileSystems(Image image) throws TskCoreException {
8009  List<FileSystem> fileSystems = new ArrayList<>();
8010  CaseDbConnection connection = connections.getConnection();
8011 
8013  Statement s = null;
8014  ResultSet rs = null;
8015  String queryStr = "SELECT * FROM tsk_fs_info WHERE data_source_obj_id = " + image.getId();
8016  try {
8017  s = connection.createStatement();
8018  rs = connection.executeQuery(s, queryStr); //NON-NLS
8019  while (rs.next()) {
8020  TskData.TSK_FS_TYPE_ENUM fsType = TskData.TSK_FS_TYPE_ENUM.valueOf(rs.getInt("fs_type")); //NON-NLS
8021  FileSystem fs = new FileSystem(this, rs.getLong("obj_id"), "", rs.getLong("img_offset"), //NON-NLS
8022  fsType, rs.getLong("block_size"), rs.getLong("block_count"), //NON-NLS
8023  rs.getLong("root_inum"), rs.getLong("first_inum"), rs.getLong("last_inum")); //NON-NLS
8024  fs.setParent(null);
8025  fileSystems.add(fs);
8026  }
8027  } catch (SQLException ex) {
8028  throw new TskCoreException("Error looking up files systems. Query: " + queryStr, ex); //NON-NLS
8029  } finally {
8030  closeResultSet(rs);
8031  closeStatement(s);
8032  connection.close();
8034  }
8035  return fileSystems;
8036  }
8037 
8048  List<Content> getImageChildren(Image img) throws TskCoreException {
8049  Collection<ObjectInfo> childInfos = getChildrenInfo(img);
8050  List<Content> children = new ArrayList<Content>();
8051  for (ObjectInfo info : childInfos) {
8052  if (null != info.type) {
8053  switch (info.type) {
8054  case VS:
8055  children.add(getVolumeSystemById(info.id, img));
8056  break;
8057  case POOL:
8058  children.add(getPoolById(info.id, img));
8059  break;
8060  case FS:
8061  children.add(getFileSystemById(info.id, img));
8062  break;
8063  case ABSTRACTFILE:
8064  AbstractFile f = getAbstractFileById(info.id);
8065  if (f != null) {
8066  children.add(f);
8067  }
8068  break;
8069  case ARTIFACT:
8070  BlackboardArtifact art = getArtifactById(info.id);
8071  if (art != null) {
8072  children.add(art);
8073  }
8074  break;
8075  case REPORT:
8076  // Do nothing for now - see JIRA-3673
8077  break;
8078  default:
8079  throw new TskCoreException("Image has child of invalid type: " + info.type);
8080  }
8081  }
8082  }
8083  return children;
8084  }
8085 
8096  List<Long> getImageChildrenIds(Image img) throws TskCoreException {
8097  Collection<ObjectInfo> childInfos = getChildrenInfo(img);
8098  List<Long> children = new ArrayList<Long>();
8099  for (ObjectInfo info : childInfos) {
8100  if (info.type == ObjectType.VS
8101  || info.type == ObjectType.POOL
8102  || info.type == ObjectType.FS
8103  || info.type == ObjectType.ABSTRACTFILE
8104  || info.type == ObjectType.ARTIFACT) {
8105  children.add(info.id);
8106  } else if (info.type == ObjectType.REPORT) {
8107  // Do nothing for now - see JIRA-3673
8108  } else {
8109  throw new TskCoreException("Image has child of invalid type: " + info.type);
8110  }
8111  }
8112  return children;
8113  }
8114 
8125  List<Content> getPoolChildren(Pool pool) throws TskCoreException {
8126  Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
8127  List<Content> children = new ArrayList<Content>();
8128  for (ObjectInfo info : childInfos) {
8129  if (null != info.type) {
8130  switch (info.type) {
8131  case VS:
8132  children.add(getVolumeSystemById(info.id, pool));
8133  break;
8134  case ABSTRACTFILE:
8135  AbstractFile f = getAbstractFileById(info.id);
8136  if (f != null) {
8137  children.add(f);
8138  }
8139  break;
8140  case ARTIFACT:
8141  BlackboardArtifact art = getArtifactById(info.id);
8142  if (art != null) {
8143  children.add(art);
8144  }
8145  break;
8146  default:
8147  throw new TskCoreException("Pool has child of invalid type: " + info.type);
8148  }
8149  }
8150  }
8151  return children;
8152  }
8153 
8164  List<Long> getPoolChildrenIds(Pool pool) throws TskCoreException {
8165  Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
8166  List<Long> children = new ArrayList<Long>();
8167  for (ObjectInfo info : childInfos) {
8168  if (info.type == ObjectType.VS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
8169  children.add(info.id);
8170  } else {
8171  throw new TskCoreException("Pool has child of invalid type: " + info.type);
8172  }
8173  }
8174  return children;
8175  }
8176 
8187  List<Content> getVolumeSystemChildren(VolumeSystem vs) throws TskCoreException {
8188  Collection<ObjectInfo> childInfos = getChildrenInfo(vs);
8189  List<Content> children = new ArrayList<Content>();
8190  for (ObjectInfo info : childInfos) {
8191  if (null != info.type) {
8192  switch (info.type) {
8193  case VOL:
8194  children.add(getVolumeById(info.id, vs));
8195  break;
8196  case ABSTRACTFILE:
8197  AbstractFile f = getAbstractFileById(info.id);
8198  if (f != null) {
8199  children.add(f);
8200  }
8201  break;
8202  case ARTIFACT:
8203  BlackboardArtifact art = getArtifactById(info.id);
8204  if (art != null) {
8205  children.add(art);
8206  }
8207  break;
8208  default:
8209  throw new TskCoreException("VolumeSystem has child of invalid type: " + info.type);
8210  }
8211  }
8212  }
8213  return children;
8214  }
8215 
8226  List<Long> getVolumeSystemChildrenIds(VolumeSystem vs) throws TskCoreException {
8227  Collection<ObjectInfo> childInfos = getChildrenInfo(vs);
8228  List<Long> children = new ArrayList<Long>();
8229  for (ObjectInfo info : childInfos) {
8230  if (info.type == ObjectType.VOL || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
8231  children.add(info.id);
8232  } else {
8233  throw new TskCoreException("VolumeSystem has child of invalid type: " + info.type);
8234  }
8235  }
8236  return children;
8237  }
8238 
8249  List<Content> getVolumeChildren(Volume vol) throws TskCoreException {
8250  Collection<ObjectInfo> childInfos = getChildrenInfo(vol);
8251  List<Content> children = new ArrayList<Content>();
8252  for (ObjectInfo info : childInfos) {
8253  if (null != info.type) {
8254  switch (info.type) {
8255  case POOL:
8256  children.add(getPoolById(info.id, vol));
8257  break;
8258  case FS:
8259  children.add(getFileSystemById(info.id, vol));
8260  break;
8261  case ABSTRACTFILE:
8262  AbstractFile f = getAbstractFileById(info.id);
8263  if (f != null) {
8264  children.add(f);
8265  }
8266  break;
8267  case ARTIFACT:
8268  BlackboardArtifact art = getArtifactById(info.id);
8269  if (art != null) {
8270  children.add(art);
8271  }
8272  break;
8273  default:
8274  throw new TskCoreException("Volume has child of invalid type: " + info.type);
8275  }
8276  }
8277  }
8278  return children;
8279  }
8280 
8291  List<Long> getVolumeChildrenIds(Volume vol) throws TskCoreException {
8292  final Collection<ObjectInfo> childInfos = getChildrenInfo(vol);
8293  final List<Long> children = new ArrayList<Long>();
8294  for (ObjectInfo info : childInfos) {
8295  if (info.type == ObjectType.FS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
8296  children.add(info.id);
8297  } else {
8298  throw new TskCoreException("Volume has child of invalid type: " + info.type);
8299  }
8300  }
8301  return children;
8302  }
8303 
8317  public Image addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone) throws TskCoreException {
8318  long imageId = this.caseHandle.addImageInfo(deviceObjId, imageFilePaths, timeZone, this);
8319  return getImageById(imageId);
8320  }
8321 
8331  public Map<Long, List<String>> getImagePaths() throws TskCoreException {
8332  CaseDbConnection connection = connections.getConnection();
8334  Statement s1 = null;
8335  ResultSet rs1 = null;
8336  try {
8337  s1 = connection.createStatement();
8338  rs1 = connection.executeQuery(s1, "SELECT tsk_image_info.obj_id, tsk_image_names.name FROM tsk_image_info " +
8339  "LEFT JOIN tsk_image_names ON tsk_image_info.obj_id = tsk_image_names.obj_id"); //NON-NLS
8340  Map<Long, List<String>> imgPaths = new LinkedHashMap<Long, List<String>>();
8341  while (rs1.next()) {
8342  long obj_id = rs1.getLong("obj_id"); //NON-NLS
8343  String name = rs1.getString("name"); //NON-NLS
8344  List<String> imagePaths = imgPaths.get(obj_id);
8345  if (imagePaths == null) {
8346  List<String> paths = new ArrayList<String>();
8347  if (name != null) {
8348  paths.add(name);
8349  }
8350  imgPaths.put(obj_id, paths);
8351  } else {
8352  if (name != null) {
8353  imagePaths.add(name);
8354  }
8355  }
8356  }
8357  return imgPaths;
8358  } catch (SQLException ex) {
8359  throw new TskCoreException("Error getting image paths.", ex);
8360  } finally {
8361  closeResultSet(rs1);
8362  closeStatement(s1);
8363  connection.close();
8365  }
8366  }
8367 
8378  private List<String> getImagePathsById(long objectId) throws TskCoreException {
8379  List<String> imagePaths = new ArrayList<String>();
8380  CaseDbConnection connection = connections.getConnection();
8382  Statement statement = null;
8383  ResultSet resultSet = null;
8384  try {
8385  statement = connection.createStatement();
8386  resultSet = connection.executeQuery(statement, "SELECT name FROM tsk_image_names WHERE tsk_image_names.obj_id = " + objectId); //NON-NLS
8387  while (resultSet.next()) {
8388  imagePaths.add(resultSet.getString("name"));
8389  }
8390  } catch (SQLException ex) {
8391  throw new TskCoreException(String.format("Error getting image names with obj_id = %d", objectId), ex);
8392  } finally {
8393  closeResultSet(resultSet);
8394  closeStatement(statement);
8395  connection.close();
8397  }
8398 
8399  return imagePaths;
8400  }
8401 
8408  public List<Image> getImages() throws TskCoreException {
8409  CaseDbConnection connection = connections.getConnection();
8411  Statement s = null;
8412  ResultSet rs = null;
8413  try {
8414  s = connection.createStatement();
8415  rs = connection.executeQuery(s, "SELECT obj_id FROM tsk_image_info"); //NON-NLS
8416  Collection<Long> imageIDs = new ArrayList<Long>();
8417  while (rs.next()) {
8418  imageIDs.add(rs.getLong("obj_id")); //NON-NLS
8419  }
8420  List<Image> images = new ArrayList<Image>();
8421  for (long id : imageIDs) {
8422  images.add(getImageById(id));
8423  }
8424  return images;
8425  } catch (SQLException ex) {
8426  throw new TskCoreException("Error retrieving images.", ex);
8427  } finally {
8428  closeResultSet(rs);
8429  closeStatement(s);
8430  connection.close();
8432  }
8433  }
8434 
8445  public void setImagePaths(long obj_id, List<String> paths) throws TskCoreException {
8446  CaseDbConnection connection = connections.getConnection();
8448  PreparedStatement statement = null;
8449  try {
8450  connection.beginTransaction();
8451  statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_IMAGE_NAME);
8452  statement.clearParameters();
8453  statement.setLong(1, obj_id);
8454  connection.executeUpdate(statement);
8455  for (int i = 0; i < paths.size(); i++) {
8456  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
8457  statement.clearParameters();
8458  statement.setLong(1, obj_id);
8459  statement.setString(2, paths.get(i));
8460  statement.setLong(3, i);
8461  connection.executeUpdate(statement);
8462  }
8463  connection.commitTransaction();
8464  } catch (SQLException ex) {
8465  connection.rollbackTransaction();
8466  throw new TskCoreException("Error updating image paths.", ex);
8467  } finally {
8468  connection.close();
8470  }
8471  }
8472 
8484  void deleteDataSource(long dataSourceObjectId) throws TskCoreException {
8485  CaseDbConnection connection = connections.getConnection();
8486  Statement statement = null;
8488  try {
8489  statement = connection.createStatement();
8490  connection.beginTransaction();
8491  // The following delete(s) uses a foreign key delete with cascade in the DB so that it will delete
8492  // all associated rows from tsk_object and its children. For large data sources this may take some time.
8493  statement.execute("DELETE FROM tsk_objects WHERE obj_id = " + dataSourceObjectId);
8494  // The following delete uses a foreign key delete with cascade in the DB so that it will delete all
8495  // associated rows from accounts table and its children.
8496  String accountSql = "DELETE FROM accounts WHERE account_id in (SELECT account_id FROM accounts "
8497  + "WHERE account_id NOT IN (SELECT account1_id FROM account_relationships) "
8498  + "AND account_id NOT IN (SELECT account2_id FROM account_relationships))";
8499  statement.execute(accountSql);
8500  connection.commitTransaction();
8501  } catch (SQLException ex) {
8502  connection.rollbackTransaction();
8503  throw new TskCoreException("Error deleting data source.", ex);
8504  } finally {
8505  connection.close();
8507  }
8508  }
8509 
8535  private List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnection connection) throws SQLException {
8536  ArrayList<AbstractFile> results = new ArrayList<AbstractFile>();
8537  try {
8538  while (rs.next()) {
8539  final short type = rs.getShort("type"); //NON-NLS
8540  if (type == TSK_DB_FILES_TYPE_ENUM.FS.getFileType()
8541  && (rs.getShort("meta_type") != TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue())) {
8542  FsContent result;
8543  if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()) { //NON-NLS
8544  result = directory(rs, null);
8545  } else {
8546  result = file(rs, null);
8547  }
8548  results.add(result);
8549  } else if (type == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
8550  || (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue())) { //NON-NLS
8551  final VirtualDirectory virtDir = virtualDirectory(rs, connection);
8552  results.add(virtDir);
8553  } else if (type == TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR.getFileType()) {
8554  final LocalDirectory localDir = localDirectory(rs);
8555  results.add(localDir);
8556  } else if (type == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
8557  || type == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
8558  || type == TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()
8559  || type == TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType()) {
8560  TSK_DB_FILES_TYPE_ENUM atype = TSK_DB_FILES_TYPE_ENUM.valueOf(type);
8561  String parentPath = rs.getString("parent_path"); //NON-NLS
8562  if (parentPath == null) {
8563  parentPath = "/"; //NON-NLS
8564  }
8565  LayoutFile lf = new LayoutFile(this,
8566  rs.getLong("obj_id"), //NON-NLS
8567  rs.getLong("data_source_obj_id"),
8568  rs.getString("name"), //NON-NLS
8569  atype,
8570  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8571  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
8572  rs.getLong("size"), //NON-NLS
8573  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8574  rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type")); //NON-NLS
8575  results.add(lf);
8576  } else if (type == TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()) {
8577  final DerivedFile df;
8578  df = derivedFile(rs, connection, AbstractContent.UNKNOWN_ID);
8579  results.add(df);
8580  } else if (type == TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()) {
8581  final LocalFile lf;
8582  lf = localFile(rs, connection, AbstractContent.UNKNOWN_ID);
8583  results.add(lf);
8584  } else if (type == TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()) {
8585  final SlackFile sf = slackFile(rs, null);
8586  results.add(sf);
8587  }
8588  } //end for each resultSet
8589  } catch (SQLException e) {
8590  logger.log(Level.SEVERE, "Error getting abstract files from result set", e); //NON-NLS
8591  }
8592 
8593  return results;
8594  }
8595 
8596  // This following methods generate AbstractFile objects from a ResultSet
8608  org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLException {
8609  org.sleuthkit.datamodel.File f = new org.sleuthkit.datamodel.File(this, rs.getLong("obj_id"), //NON-NLS
8610  rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
8611  TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
8612  rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
8613  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8614  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8615  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8616  rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
8617  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8618  (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
8619  rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8620  rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension")); //NON-NLS
8621  f.setFileSystem(fs);
8622  return f;
8623  }
8624 
8636  Directory directory(ResultSet rs, FileSystem fs) throws SQLException {
8637  Directory dir = new Directory(this, rs.getLong("obj_id"), rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
8638  TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
8639  rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
8640  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8641  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8642  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8643  rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
8644  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8645  rs.getShort("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
8646  rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8647  rs.getString("parent_path")); //NON-NLS
8648  dir.setFileSystem(fs);
8649  return dir;
8650  }
8651 
8662  VirtualDirectory virtualDirectory(ResultSet rs, CaseDbConnection connection) throws SQLException {
8663  String parentPath = rs.getString("parent_path"); //NON-NLS
8664  if (parentPath == null) {
8665  parentPath = "";
8666  }
8667 
8668  long objId = rs.getLong("obj_id");
8669  long dsObjId = rs.getLong("data_source_obj_id");
8670  if (objId == dsObjId) { // virtual directory is a data source
8671 
8672  String deviceId = "";
8673  String timeZone = "";
8674  Statement s = null;
8675  ResultSet rsDataSourceInfo = null;
8676 
8678  try {
8679  s = connection.createStatement();
8680  rsDataSourceInfo = connection.executeQuery(s, "SELECT device_id, time_zone FROM data_source_info WHERE obj_id = " + objId);
8681  if (rsDataSourceInfo.next()) {
8682  deviceId = rsDataSourceInfo.getString("device_id");
8683  timeZone = rsDataSourceInfo.getString("time_zone");
8684  }
8685  } catch (SQLException ex) {
8686  logger.log(Level.SEVERE, "Error data source info for datasource id " + objId, ex); //NON-NLS
8687  } finally {
8688  closeResultSet(rsDataSourceInfo);
8689  closeStatement(s);
8691  }
8692 
8693  return new LocalFilesDataSource(this,
8694  objId, dsObjId,
8695  deviceId,
8696  rs.getString("name"),
8697  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8698  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8699  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")),
8700  rs.getShort("meta_flags"),
8701  timeZone,
8702  rs.getString("md5"),
8703  rs.getString("sha256"),
8704  FileKnown.valueOf(rs.getByte("known")),
8705  parentPath);
8706  } else {
8707  final VirtualDirectory vd = new VirtualDirectory(this,
8708  objId, dsObjId,
8709  rs.getString("name"), //NON-NLS
8710  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8711  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8712  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8713  rs.getShort("meta_flags"), rs.getString("md5"), rs.getString("sha256"), //NON-NLS
8714  FileKnown.valueOf(rs.getByte("known")), parentPath); //NON-NLS
8715  return vd;
8716  }
8717  }
8718 
8728  LocalDirectory localDirectory(ResultSet rs) throws SQLException {
8729  String parentPath = rs.getString("parent_path"); //NON-NLS
8730  if (parentPath == null) {
8731  parentPath = "";
8732  }
8733  final LocalDirectory ld = new LocalDirectory(this, rs.getLong("obj_id"), //NON-NLS
8734  rs.getLong("data_source_obj_id"), rs.getString("name"), //NON-NLS
8735  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8736  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8737  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8738  rs.getShort("meta_flags"), rs.getString("md5"), rs.getString("sha256"), //NON-NLS
8739  FileKnown.valueOf(rs.getByte("known")), parentPath); //NON-NLS
8740  return ld;
8741  }
8742 
8756  private DerivedFile derivedFile(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
8757  boolean hasLocalPath = rs.getBoolean("has_path"); //NON-NLS
8758  long objId = rs.getLong("obj_id"); //NON-NLS
8759  String localPath = null;
8760  TskData.EncodingType encodingType = TskData.EncodingType.NONE;
8761  if (hasLocalPath) {
8762  ResultSet rsFilePath = null;
8764  try {
8765  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE);
8766  statement.clearParameters();
8767  statement.setLong(1, objId);
8768  rsFilePath = connection.executeQuery(statement);
8769  if (rsFilePath.next()) {
8770  localPath = rsFilePath.getString("path");
8771  encodingType = TskData.EncodingType.valueOf(rsFilePath.getInt("encoding_type"));
8772  }
8773  } catch (SQLException ex) {
8774  logger.log(Level.SEVERE, "Error getting encoding type for file " + objId, ex); //NON-NLS
8775  } finally {
8776  closeResultSet(rsFilePath);
8778  }
8779  }
8780  String parentPath = rs.getString("parent_path"); //NON-NLS
8781  if (parentPath == null) {
8782  parentPath = "";
8783  }
8784  final DerivedFile df = new DerivedFile(this, objId, rs.getLong("data_source_obj_id"),
8785  rs.getString("name"), //NON-NLS
8786  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8787  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8788  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
8789  rs.getLong("size"), //NON-NLS
8790  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8791  rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8792  parentPath, localPath, parentId, rs.getString("mime_type"),
8793  encodingType, rs.getString("extension"));
8794  return df;
8795  }
8796 
8810  private LocalFile localFile(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
8811  long objId = rs.getLong("obj_id"); //NON-NLS
8812  String localPath = null;
8813  TskData.EncodingType encodingType = TskData.EncodingType.NONE;
8814  if (rs.getBoolean("has_path")) {
8815  ResultSet rsFilePath = null;
8817  try {
8818  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE);
8819  statement.clearParameters();
8820  statement.setLong(1, objId);
8821  rsFilePath = connection.executeQuery(statement);
8822  if (rsFilePath.next()) {
8823  localPath = rsFilePath.getString("path");
8824  encodingType = TskData.EncodingType.valueOf(rsFilePath.getInt("encoding_type"));
8825  }
8826  } catch (SQLException ex) {
8827  logger.log(Level.SEVERE, "Error getting encoding type for file " + objId, ex); //NON-NLS
8828  } finally {
8829  closeResultSet(rsFilePath);
8831  }
8832  }
8833  String parentPath = rs.getString("parent_path"); //NON-NLS
8834  if (null == parentPath) {
8835  parentPath = "";
8836  }
8837  LocalFile file = new LocalFile(this, objId, rs.getString("name"), //NON-NLS
8838  TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type")), //NON-NLS
8839  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8840  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8841  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
8842  rs.getLong("size"), //NON-NLS
8843  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8844  rs.getString("mime_type"), rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8845  parentId, parentPath, rs.getLong("data_source_obj_id"),
8846  localPath, encodingType, rs.getString("extension"));
8847  return file;
8848  }
8849 
8861  org.sleuthkit.datamodel.SlackFile slackFile(ResultSet rs, FileSystem fs) throws SQLException {
8862  org.sleuthkit.datamodel.SlackFile f = new org.sleuthkit.datamodel.SlackFile(this, rs.getLong("obj_id"), //NON-NLS
8863  rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
8864  TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
8865  rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
8866  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
8867  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
8868  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
8869  rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
8870  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
8871  (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
8872  rs.getString("md5"), rs.getString("sha256"), FileKnown.valueOf(rs.getByte("known")), //NON-NLS
8873  rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension")); //NON-NLS
8874  f.setFileSystem(fs);
8875  return f;
8876  }
8877 
8889  List<Content> fileChildren(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
8890  List<Content> children = new ArrayList<Content>();
8891 
8892  while (rs.next()) {
8893  TskData.TSK_DB_FILES_TYPE_ENUM type = TskData.TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type"));
8894 
8895  if (null != type) {
8896  switch (type) {
8897  case FS:
8898  if (rs.getShort("meta_type") != TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()) {
8899  FsContent result;
8900  if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()) {
8901  result = directory(rs, null);
8902  } else {
8903  result = file(rs, null);
8904  }
8905  children.add(result);
8906  } else {
8907  VirtualDirectory virtDir = virtualDirectory(rs, connection);
8908  children.add(virtDir);
8909  }
8910  break;
8911  case VIRTUAL_DIR:
8912  VirtualDirectory virtDir = virtualDirectory(rs, connection);
8913  children.add(virtDir);
8914  break;
8915  case LOCAL_DIR:
8916  LocalDirectory localDir = localDirectory(rs);
8917  children.add(localDir);
8918  break;
8919  case UNALLOC_BLOCKS:
8920  case UNUSED_BLOCKS:
8921  case CARVED:
8922  case LAYOUT_FILE: {
8923  String parentPath = rs.getString("parent_path");
8924  if (parentPath == null) {
8925  parentPath = "";
8926  }
8927  final LayoutFile lf = new LayoutFile(this, rs.getLong("obj_id"),
8928  rs.getLong("data_source_obj_id"), rs.getString("name"), type,
8929  TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")),
8930  TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")),
8931  TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"),
8932  rs.getLong("size"),
8933  rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"),
8934  rs.getString("md5"), rs.getString("sha256"),
8935  FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type"));
8936  children.add(lf);
8937  break;
8938  }
8939  case DERIVED:
8940  final DerivedFile df = derivedFile(rs, connection, parentId);
8941  children.add(df);
8942  break;
8943  case LOCAL: {
8944  final LocalFile lf = localFile(rs, connection, parentId);
8945  children.add(lf);
8946  break;
8947  }
8948  case SLACK: {
8949  final SlackFile sf = slackFile(rs, null);
8950  children.add(sf);
8951  break;
8952  }
8953  default:
8954  break;
8955  }
8956  }
8957  }
8958  return children;
8959  }
8960 
8976  private List<BlackboardArtifact> resultSetToArtifacts(ResultSet rs) throws SQLException, TskCoreException {
8977  ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
8978  try {
8979  while (rs.next()) {
8980  BlackboardArtifact.Type artifactType = getArtifactType(rs.getInt("artifact_type_id"));
8981  if (artifactType != null) {
8982  artifacts.add(new BlackboardArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
8983  rs.getInt("artifact_type_id"), artifactType.getTypeName(), artifactType.getDisplayName(),
8984  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
8985  } else {
8986  throw new TskCoreException("Error looking up artifact type ID " + rs.getInt("artifact_type_id") + " from artifact " + rs.getLong("artifact_id"));
8987  }
8988  } //end for each resultSet
8989  } catch (SQLException e) {
8990  logger.log(Level.SEVERE, "Error getting artifacts from result set", e); //NON-NLS
8991  }
8992 
8993  return artifacts;
8994  }
8995 
9017  public CaseDbQuery executeQuery(String query) throws TskCoreException {
9018  return new CaseDbQuery(query);
9019  }
9020 
9042  public CaseDbQuery executeInsertOrUpdate(String query) throws TskCoreException {
9043  return new CaseDbQuery(query, true);
9044  }
9045 
9053  CaseDbConnection getConnection() throws TskCoreException {
9054  return connections.getConnection();
9055  }
9056 
9063  String getCaseHandleIdentifier() {
9064  return caseHandleIdentifier;
9065  }
9066 
9067  @Override
9068  protected void finalize() throws Throwable {
9069  try {
9070  close();
9071  } finally {
9072  super.finalize();
9073  }
9074  }
9075 
9079  public synchronized void close() {
9081 
9082  try {
9083  connections.close();
9084  } catch (TskCoreException ex) {
9085  logger.log(Level.SEVERE, "Error closing database connection pool.", ex); //NON-NLS
9086  }
9087 
9088  fileSystemIdMap.clear();
9089 
9090  try {
9091  if (this.caseHandle != null) {
9092  this.caseHandle.free();
9093  this.caseHandle = null;
9094  }
9095  } catch (TskCoreException ex) {
9096  logger.log(Level.SEVERE, "Error freeing case handle.", ex); //NON-NLS
9097  } finally {
9099  }
9100  }
9101 
9114  public boolean setKnown(AbstractFile file, FileKnown fileKnown) throws TskCoreException {
9115  long id = file.getId();
9116  FileKnown currentKnown = file.getKnown();
9117  if (currentKnown.compareTo(fileKnown) > 0) {
9118  return false;
9119  }
9120  CaseDbConnection connection = connections.getConnection();
9122  Statement statement = null;
9123  try {
9124  statement = connection.createStatement();
9125  connection.executeUpdate(statement, "UPDATE tsk_files " //NON-NLS
9126  + "SET known='" + fileKnown.getFileKnownValue() + "' " //NON-NLS
9127  + "WHERE obj_id=" + id); //NON-NLS
9128 
9129  file.setKnown(fileKnown);
9130  } catch (SQLException ex) {
9131  throw new TskCoreException("Error setting Known status.", ex);
9132  } finally {
9133  closeStatement(statement);
9134  connection.close();
9136  }
9137  return true;
9138  }
9139 
9148  void setFileName(String name, long objId) throws TskCoreException {
9149 
9150  CaseDbConnection connection = connections.getConnection();
9152  try {
9153  PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_FILE_NAME);
9154  preparedStatement.clearParameters();
9155  preparedStatement.setString(1, name);
9156  preparedStatement.setLong(2, objId);
9157  connection.executeUpdate(preparedStatement);
9158  } catch (SQLException ex) {
9159  throw new TskCoreException(String.format("Error updating while the name for object ID %d to %s", objId, name), ex);
9160  } finally {
9161  connection.close();
9163  }
9164  }
9165 
9174  void setImageName(String name, long objId) throws TskCoreException {
9175 
9176  CaseDbConnection connection = connections.getConnection();
9178  try {
9179  PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_IMAGE_NAME);
9180  preparedStatement.clearParameters();
9181  preparedStatement.setString(1, name);
9182  preparedStatement.setLong(2, objId);
9183  connection.executeUpdate(preparedStatement);
9184  } catch (SQLException ex) {
9185  throw new TskCoreException(String.format("Error updating while the name for object ID %d to %s", objId, name), ex);
9186  } finally {
9187  connection.close();
9189  }
9190  }
9191 
9201  public void setFileMIMEType(AbstractFile file, String mimeType) throws TskCoreException {
9202  CaseDbConnection connection = connections.getConnection();
9203  Statement statement = null;
9204  ResultSet rs = null;
9206  try {
9207  statement = connection.createStatement();
9208  connection.executeUpdate(statement, String.format("UPDATE tsk_files SET mime_type = '%s' WHERE obj_id = %d", mimeType, file.getId()));
9209  file.setMIMEType(mimeType);
9210  } catch (SQLException ex) {
9211  throw new TskCoreException(String.format("Error setting MIME type for file (obj_id = %s)", file.getId()), ex);
9212  } finally {
9213  closeResultSet(rs);
9214  closeStatement(statement);
9215  connection.close();
9217  }
9218  }
9219 
9229  void setMd5Hash(AbstractFile file, String md5Hash) throws TskCoreException {
9230  if (md5Hash == null) {
9231  return;
9232  }
9233  long id = file.getId();
9234  CaseDbConnection connection = connections.getConnection();
9236  try {
9237  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_FILE_MD5);
9238  statement.clearParameters();
9239  statement.setString(1, md5Hash.toLowerCase());
9240  statement.setLong(2, id);
9241  connection.executeUpdate(statement);
9242  file.setMd5Hash(md5Hash.toLowerCase());
9243  } catch (SQLException ex) {
9244  throw new TskCoreException("Error setting MD5 hash", ex);
9245  } finally {
9246  connection.close();
9248  }
9249  }
9250 
9260  void setMd5ImageHash(Image img, String md5Hash) throws TskCoreException {
9261  if (md5Hash == null) {
9262  return;
9263  }
9264  long id = img.getId();
9265  CaseDbConnection connection = connections.getConnection();
9267  try {
9268  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_MD5);
9269  statement.clearParameters();
9270  statement.setString(1, md5Hash.toLowerCase());
9271  statement.setLong(2, id);
9272  connection.executeUpdate(statement);
9273  } catch (SQLException ex) {
9274  throw new TskCoreException("Error setting MD5 hash", ex);
9275  } finally {
9276  connection.close();
9278  }
9279  }
9280 
9291  String getMd5ImageHash(Image img) throws TskCoreException {
9292  long id = img.getId();
9293  CaseDbConnection connection = connections.getConnection();
9295  ResultSet rs = null;
9296  String hash = "";
9297  try {
9298  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_MD5);
9299  statement.clearParameters();
9300  statement.setLong(1, id);
9301  rs = connection.executeQuery(statement);
9302  if (rs.next()) {
9303  hash = rs.getString("md5");
9304  }
9305  return hash;
9306  } catch (SQLException ex) {
9307  throw new TskCoreException("Error getting MD5 hash", ex);
9308  } finally {
9309  closeResultSet(rs);
9310  connection.close();
9312  }
9313  }
9314 
9324  void setSha1ImageHash(Image img, String sha1Hash) throws TskCoreException {
9325  if (sha1Hash == null) {
9326  return;
9327  }
9328  long id = img.getId();
9329  CaseDbConnection connection = connections.getConnection();
9331  try {
9332  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_SHA1);
9333  statement.clearParameters();
9334  statement.setString(1, sha1Hash.toLowerCase());
9335  statement.setLong(2, id);
9336  connection.executeUpdate(statement);
9337  } catch (SQLException ex) {
9338  throw new TskCoreException("Error setting SHA1 hash", ex);
9339  } finally {
9340  connection.close();
9342  }
9343  }
9344 
9355  String getSha1ImageHash(Image img) throws TskCoreException {
9356  long id = img.getId();
9357  CaseDbConnection connection = connections.getConnection();
9359  ResultSet rs = null;
9360  String hash = "";
9361  try {
9362  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_SHA1);
9363  statement.clearParameters();
9364  statement.setLong(1, id);
9365  rs = connection.executeQuery(statement);
9366  if (rs.next()) {
9367  hash = rs.getString("sha1");
9368  }
9369  return hash;
9370  } catch (SQLException ex) {
9371  throw new TskCoreException("Error getting SHA1 hash", ex);
9372  } finally {
9373  closeResultSet(rs);
9374  connection.close();
9376  }
9377  }
9378 
9388  void setSha256ImageHash(Image img, String sha256Hash) throws TskCoreException {
9389  if (sha256Hash == null) {
9390  return;
9391  }
9392  long id = img.getId();
9393  CaseDbConnection connection = connections.getConnection();
9395  try {
9396  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_SHA256);
9397  statement.clearParameters();
9398  statement.setString(1, sha256Hash.toLowerCase());
9399  statement.setLong(2, id);
9400  connection.executeUpdate(statement);
9401  } catch (SQLException ex) {
9402  throw new TskCoreException("Error setting SHA256 hash", ex);
9403  } finally {
9404  connection.close();
9406  }
9407  }
9408 
9419  String getSha256ImageHash(Image img) throws TskCoreException {
9420  long id = img.getId();
9421  CaseDbConnection connection = connections.getConnection();
9423  ResultSet rs = null;
9424  String hash = "";
9425  try {
9426  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_SHA256);
9427  statement.clearParameters();
9428  statement.setLong(1, id);
9429  rs = connection.executeQuery(statement);
9430  if (rs.next()) {
9431  hash = rs.getString("sha256");
9432  }
9433  return hash;
9434  } catch (SQLException ex) {
9435  throw new TskCoreException("Error setting SHA256 hash", ex);
9436  } finally {
9437  closeResultSet(rs);
9438  connection.close();
9440  }
9441  }
9442 
9451  void setAcquisitionDetails(DataSource datasource, String details) throws TskCoreException {
9452 
9453  long id = datasource.getId();
9454  CaseDbConnection connection = connections.getConnection();
9456  try {
9457  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
9458  statement.clearParameters();
9459  statement.setString(1, details);
9460  statement.setLong(2, id);
9461  connection.executeUpdate(statement);
9462  } catch (SQLException ex) {
9463  throw new TskCoreException("Error setting acquisition details", ex);
9464  } finally {
9465  connection.close();
9467  }
9468  }
9469 
9479  void setAcquisitionDetails(long dataSourceId, String details, CaseDbTransaction trans) throws TskCoreException {
9481  try {
9482  CaseDbConnection connection = trans.getConnection();
9483  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
9484  statement.clearParameters();
9485  statement.setString(1, details);
9486  statement.setLong(2, dataSourceId);
9487  connection.executeUpdate(statement);
9488  } catch (SQLException ex) {
9489  throw new TskCoreException("Error setting acquisition details", ex);
9490  } finally {
9492  }
9493  }
9494 
9504  String getAcquisitionDetails(DataSource datasource) throws TskCoreException {
9505  long id = datasource.getId();
9506  CaseDbConnection connection = connections.getConnection();
9508  ResultSet rs = null;
9509  String hash = "";
9510  try {
9511  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ACQUISITION_DETAILS);
9512  statement.clearParameters();
9513  statement.setLong(1, id);
9514  rs = connection.executeQuery(statement);
9515  if (rs.next()) {
9516  hash = rs.getString("acquisition_details");
9517  }
9518  return hash;
9519  } catch (SQLException ex) {
9520  throw new TskCoreException("Error setting acquisition details", ex);
9521  } finally {
9522  closeResultSet(rs);
9523  connection.close();
9525  }
9526  }
9527 
9538  public void setReviewStatus(BlackboardArtifact artifact, BlackboardArtifact.ReviewStatus newStatus) throws TskCoreException {
9539  if (newStatus == null) {
9540  return;
9541  }
9542  CaseDbConnection connection = connections.getConnection();
9544  Statement statement = null;
9545  try {
9546  statement = connection.createStatement();
9547  connection.executeUpdate(statement, "UPDATE blackboard_artifacts "
9548  + " SET review_status_id=" + newStatus.getID()
9549  + " WHERE blackboard_artifacts.artifact_id = " + artifact.getArtifactID());
9550  } catch (SQLException ex) {
9551  throw new TskCoreException("Error setting review status", ex);
9552  } finally {
9553  closeStatement(statement);
9554  connection.close();
9556  }
9557  }
9558 
9569  public int countFsContentType(TskData.TSK_FS_META_TYPE_ENUM contentType) throws TskCoreException {
9570  CaseDbConnection connection = connections.getConnection();
9572  Statement s = null;
9573  ResultSet rs = null;
9574  try {
9575  s = connection.createStatement();
9576  Short contentShort = contentType.getValue();
9577  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files WHERE meta_type = '" + contentShort.toString() + "'"); //NON-NLS
9578  int count = 0;
9579  if (rs.next()) {
9580  count = rs.getInt("count");
9581  }
9582  return count;
9583  } catch (SQLException ex) {
9584  throw new TskCoreException("Error getting number of objects.", ex);
9585  } finally {
9586  closeResultSet(rs);
9587  closeStatement(s);
9588  connection.close();
9590  }
9591  }
9592 
9601  public static String escapeSingleQuotes(String text) {
9602  String escapedText = null;
9603  if (text != null) {
9604  escapedText = text.replaceAll("'", "''");
9605  }
9606  return escapedText;
9607  }
9608 
9616  public List<AbstractFile> findFilesByMd5(String md5Hash) {
9617  if (md5Hash == null) {
9618  return Collections.<AbstractFile>emptyList();
9619  }
9620  CaseDbConnection connection;
9621  try {
9622  connection = connections.getConnection();
9623  } catch (TskCoreException ex) {
9624  logger.log(Level.SEVERE, "Error finding files by md5 hash " + md5Hash, ex); //NON-NLS
9625  return Collections.<AbstractFile>emptyList();
9626  }
9628  Statement s = null;
9629  ResultSet rs = null;
9630  try {
9631  s = connection.createStatement();
9632  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " //NON-NLS
9633  + " md5 = '" + md5Hash.toLowerCase() + "' " //NON-NLS
9634  + "AND size > 0"); //NON-NLS
9635  return resultSetToAbstractFiles(rs, connection);
9636  } catch (SQLException ex) {
9637  logger.log(Level.WARNING, "Error querying database.", ex); //NON-NLS
9638  return Collections.<AbstractFile>emptyList();
9639  } finally {
9640  closeResultSet(rs);
9641  closeStatement(s);
9642  connection.close();
9644  }
9645  }
9646 
9653  public boolean allFilesMd5Hashed() {
9654  CaseDbConnection connection;
9655  try {
9656  connection = connections.getConnection();
9657  } catch (TskCoreException ex) {
9658  logger.log(Level.SEVERE, "Error checking md5 hashing status", ex); //NON-NLS
9659  return false;
9660  }
9661  boolean allFilesAreHashed = false;
9663  Statement s = null;
9664  ResultSet rs = null;
9665  try {
9666  s = connection.createStatement();
9667  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files " //NON-NLS
9668  + "WHERE dir_type = '" + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + "' " //NON-NLS
9669  + "AND md5 IS NULL " //NON-NLS
9670  + "AND size > '0'"); //NON-NLS
9671  if (rs.next() && rs.getInt("count") == 0) {
9672  allFilesAreHashed = true;
9673  }
9674  } catch (SQLException ex) {
9675  logger.log(Level.WARNING, "Failed to query whether all files have MD5 hashes", ex); //NON-NLS
9676  } finally {
9677  closeResultSet(rs);
9678  closeStatement(s);
9679  connection.close();
9681  }
9682  return allFilesAreHashed;
9683  }
9684 
9690  public int countFilesMd5Hashed() {
9691  CaseDbConnection connection;
9692  try {
9693  connection = connections.getConnection();
9694  } catch (TskCoreException ex) {
9695  logger.log(Level.SEVERE, "Error getting database connection for hashed files count", ex); //NON-NLS
9696  return 0;
9697  }
9698  int count = 0;
9700  Statement s = null;
9701  ResultSet rs = null;
9702  try {
9703  s = connection.createStatement();
9704  rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files " //NON-NLS
9705  + "WHERE md5 IS NOT NULL " //NON-NLS
9706  + "AND size > '0'"); //NON-NLS
9707  if (rs.next()) {
9708  count = rs.getInt("count");
9709  }
9710  } catch (SQLException ex) {
9711  logger.log(Level.WARNING, "Failed to query for all the files.", ex); //NON-NLS
9712  } finally {
9713  closeResultSet(rs);
9714  closeStatement(s);
9715  connection.close();
9717  }
9718  return count;
9719 
9720  }
9721 
9730  public List<TagName> getAllTagNames() throws TskCoreException {
9731  CaseDbConnection connection = connections.getConnection();
9733  ResultSet resultSet = null;
9734  try {
9735  // SELECT * FROM tag_names
9736  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES);
9737  resultSet = connection.executeQuery(statement);
9738  ArrayList<TagName> tagNames = new ArrayList<>();
9739  while (resultSet.next()) {
9740  tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9741  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9742  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
9743  }
9744  return tagNames;
9745  } catch (SQLException ex) {
9746  throw new TskCoreException("Error selecting rows from tag_names table", ex);
9747  } finally {
9748  closeResultSet(resultSet);
9749  connection.close();
9751  }
9752  }
9753 
9764  public List<TagName> getTagNamesInUse() throws TskCoreException {
9765  CaseDbConnection connection = connections.getConnection();
9767  ResultSet resultSet = null;
9768  try {
9769  // 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)
9770  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES_IN_USE);
9771  resultSet = connection.executeQuery(statement);
9772  ArrayList<TagName> tagNames = new ArrayList<>();
9773  while (resultSet.next()) {
9774  tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9775  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9776  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
9777  }
9778  return tagNames;
9779  } catch (SQLException ex) {
9780  throw new TskCoreException("Error selecting rows from tag_names table", ex);
9781  } finally {
9782  closeResultSet(resultSet);
9783  connection.close();
9785  }
9786  }
9787 
9800  public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
9801 
9802  ArrayList<TagName> tagNames = new ArrayList<TagName>();
9803  // SELECT * FROM tag_names WHERE tag_name_id IN
9804  // ( 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 = ? "
9805  // UNION
9806  // 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 = ? )
9807  // )
9808  CaseDbConnection connection = connections.getConnection();
9810  ResultSet resultSet = null;
9811 
9812  try {
9813  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES_IN_USE_BY_DATASOURCE);
9814  statement.setLong(1, dsObjId);
9815  statement.setLong(2, dsObjId);
9816  resultSet = connection.executeQuery(statement); //NON-NLS
9817  while (resultSet.next()) {
9818  tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9819  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9820  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
9821  }
9822  return tagNames;
9823  } catch (SQLException ex) {
9824  throw new TskCoreException("Failed to get tag names in use for data source objID : " + dsObjId, ex);
9825  } finally {
9826  closeResultSet(resultSet);
9827  connection.close();
9829  }
9830  }
9831 
9845  @Deprecated
9846  public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TskCoreException {
9847  return addOrUpdateTagName(displayName, description, color, TskData.FileKnown.UNKNOWN);
9848  }
9849 
9864  public TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TskCoreException {
9865  CaseDbConnection connection = connections.getConnection();
9867  ResultSet resultSet = null;
9868  try {
9869  PreparedStatement statement;
9870  // INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?) ON CONFLICT (display_name) DO UPDATE SET description = ?, color = ?, knownStatus = ?
9871  statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OR_UPDATE_TAG_NAME, Statement.RETURN_GENERATED_KEYS);
9872  statement.clearParameters();
9873  statement.setString(5, description);
9874  statement.setString(6, color.getName());
9875  statement.setByte(7, knownStatus.getFileKnownValue());
9876  statement.setString(1, displayName);
9877  statement.setString(2, description);
9878  statement.setString(3, color.getName());
9879  statement.setByte(4, knownStatus.getFileKnownValue());
9880  connection.executeUpdate(statement);
9881 
9882  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAME_BY_NAME);
9883  statement.clearParameters();
9884  statement.setString(1, displayName);
9885  resultSet = connection.executeQuery(statement);
9886  resultSet.next();
9887 
9888  return new TagName(resultSet.getLong("tag_name_id"), displayName, description, color, knownStatus, resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
9889 
9890  } catch (SQLException ex) {
9891  throw new TskCoreException("Error adding row for " + displayName + " tag name to tag_names table", ex);
9892  } finally {
9893  closeResultSet(resultSet);
9894  connection.close();
9896  }
9897  }
9898 
9913  @Deprecated
9914  public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
9915  return taggingMgr.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset).getAddedTag();
9916  }
9917 
9918  /*
9919  * Deletes a row from the content_tags table in the case database. @param
9920  * tag A ContentTag data transfer object (DTO) for the row to delete.
9921  * @throws TskCoreException
9922  */
9923  public void deleteContentTag(ContentTag tag) throws TskCoreException {
9924  CaseDbConnection connection = connections.getConnection();
9926  try {
9927  // DELETE FROM content_tags WHERE tag_id = ?
9928  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_CONTENT_TAG);
9929  statement.clearParameters();
9930  statement.setLong(1, tag.getId());
9931  connection.executeUpdate(statement);
9932  } catch (SQLException ex) {
9933  throw new TskCoreException("Error deleting row from content_tags table (id = " + tag.getId() + ")", ex);
9934  } finally {
9935  connection.close();
9937  }
9938  }
9939 
9948  public List<ContentTag> getAllContentTags() throws TskCoreException {
9949  CaseDbConnection connection = connections.getConnection();
9951  ResultSet resultSet = null;
9952  try {
9953  // 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
9954  // FROM content_tags
9955  // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
9956  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
9957  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS);
9958  resultSet = connection.executeQuery(statement);
9959  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
9960  while (resultSet.next()) {
9961  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
9962  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
9963  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
9964  Content content = getContentById(resultSet.getLong("obj_id")); //NON-NLS
9965  tags.add(new ContentTag(resultSet.getLong("tag_id"), content, tagName, resultSet.getString("comment"),
9966  resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"))); //NON-NLS
9967  }
9968  return tags;
9969  } catch (SQLException ex) {
9970  throw new TskCoreException("Error selecting rows from content_tags table", ex);
9971  } finally {
9972  closeResultSet(resultSet);
9973  connection.close();
9975  }
9976  }
9977 
9988  public long getContentTagsCountByTagName(TagName tagName) throws TskCoreException {
9989  if (tagName.getId() == Tag.ID_NOT_SET) {
9990  throw new TskCoreException("TagName object is invalid, id not set");
9991  }
9992  CaseDbConnection connection = connections.getConnection();
9994  ResultSet resultSet = null;
9995  try {
9996  // SELECT COUNT(*) AS count FROM content_tags WHERE tag_name_id = ?
9997  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CONTENT_TAGS_BY_TAG_NAME);
9998  statement.clearParameters();
9999  statement.setLong(1, tagName.getId());
10000  resultSet = connection.executeQuery(statement);
10001  if (resultSet.next()) {
10002  return resultSet.getLong("count");
10003  } else {
10004  throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")");
10005  }
10006  } catch (SQLException ex) {
10007  throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")", ex);
10008  } finally {
10009  closeResultSet(resultSet);
10010  connection.close();
10012  }
10013  }
10014 
10030  public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10031 
10032  if (tagName.getId() == Tag.ID_NOT_SET) {
10033  throw new TskCoreException("TagName object is invalid, id not set");
10034  }
10035 
10036  CaseDbConnection connection = connections.getConnection();
10038  ResultSet resultSet = null;
10039  try {
10040  // "SELECT COUNT(*) AS count FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id"
10041  // + " AND content_tags.tag_name_id = ? "
10042  // + " AND tsk_files.data_source_obj_id = ? "
10043  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
10044  statement.clearParameters();
10045  statement.setLong(1, tagName.getId());
10046  statement.setLong(2, dsObjId);
10047 
10048  resultSet = connection.executeQuery(statement);
10049  if (resultSet.next()) {
10050  return resultSet.getLong("count");
10051  } else {
10052  throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")" + " for dsObjId = " + dsObjId);
10053  }
10054  } catch (SQLException ex) {
10055  throw new TskCoreException("Failed to get content_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
10056  } finally {
10057  closeResultSet(resultSet);
10058  connection.close();
10060  }
10061  }
10062 
10073  public ContentTag getContentTagByID(long contentTagID) throws TskCoreException {
10074 
10075  CaseDbConnection connection = connections.getConnection();
10077  ResultSet resultSet = null;
10078  ContentTag tag = null;
10079  try {
10080  // 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
10081  // FROM content_tags
10082  // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
10083  // UTER LEFT JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10084  // WHERE tag_id = ?
10085  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAG_BY_ID);
10086  statement.clearParameters();
10087  statement.setLong(1, contentTagID);
10088  resultSet = connection.executeQuery(statement);
10089 
10090  while (resultSet.next()) {
10091  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10092  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10093  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
10094  tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")), tagName,
10095  resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"));
10096  }
10097  resultSet.close();
10098 
10099  } catch (SQLException ex) {
10100  throw new TskCoreException("Error getting content tag with id = " + contentTagID, ex);
10101  } finally {
10102  closeResultSet(resultSet);
10103  connection.close();
10105  }
10106  return tag;
10107  }
10108 
10120  public List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException {
10121  if (tagName.getId() == Tag.ID_NOT_SET) {
10122  throw new TskCoreException("TagName object is invalid, id not set");
10123  }
10124  CaseDbConnection connection = connections.getConnection();
10126  ResultSet resultSet = null;
10127  try {
10128  // 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
10129  // FROM content_tags
10130  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10131  // WHERE tag_name_id = ?
10132  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_TAG_NAME);
10133  statement.clearParameters();
10134  statement.setLong(1, tagName.getId());
10135  resultSet = connection.executeQuery(statement);
10136  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
10137  while (resultSet.next()) {
10138  ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")),
10139  tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
10140  tags.add(tag);
10141  }
10142  resultSet.close();
10143  return tags;
10144  } catch (SQLException ex) {
10145  throw new TskCoreException("Error getting content_tags rows (tag_name_id = " + tagName.getId() + ")", ex);
10146  } finally {
10147  closeResultSet(resultSet);
10148  connection.close();
10150  }
10151  }
10152 
10165  public List<ContentTag> getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10166 
10167  CaseDbConnection connection = connections.getConnection();
10169  ResultSet resultSet = null;
10170  try {
10171 
10172  // 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
10173  // FROM content_tags as content_tags, tsk_files as tsk_files
10174  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10175  // WHERE content_tags.obj_id = tsk_files.obj_id
10176  // AND content_tags.tag_name_id = ?
10177  // AND tsk_files.data_source_obj_id = ?
10178  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
10179  statement.clearParameters();
10180  statement.setLong(1, tagName.getId());
10181  statement.setLong(2, dsObjId);
10182  resultSet = connection.executeQuery(statement);
10183  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
10184  while (resultSet.next()) {
10185  ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")),
10186  tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
10187  tags.add(tag);
10188  }
10189  resultSet.close();
10190  return tags;
10191  } catch (SQLException ex) {
10192  throw new TskCoreException("Failed to get content_tags row count for tag_name_id = " + tagName.getId() + " data source objID : " + dsObjId, ex);
10193  } finally {
10194  closeResultSet(resultSet);
10195  connection.close();
10197  }
10198  }
10199 
10211  public List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException {
10212  CaseDbConnection connection = connections.getConnection();
10214  ResultSet resultSet = null;
10215  try {
10216  // 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
10217  // FROM content_tags
10218  // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
10219  // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
10220  // WHERE content_tags.obj_id = ?
10221  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_CONTENT);
10222  statement.clearParameters();
10223  statement.setLong(1, content.getId());
10224  resultSet = connection.executeQuery(statement);
10225  ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
10226  while (resultSet.next()) {
10227  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10228  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10229  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
10230  ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), content, tagName,
10231  resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
10232  tags.add(tag);
10233  }
10234  return tags;
10235  } catch (SQLException ex) {
10236  throw new TskCoreException("Error getting content tags data for content (obj_id = " + content.getId() + ")", ex);
10237  } finally {
10238  closeResultSet(resultSet);
10239  connection.close();
10241  }
10242  }
10243 
10258  @Deprecated
10259  public BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment) throws TskCoreException {
10260  return taggingMgr.addArtifactTag(artifact, tagName, comment).getAddedTag();
10261  }
10262 
10263  /*
10264  * Deletes a row from the blackboard_artifact_tags table in the case
10265  * database. @param tag A BlackboardArtifactTag data transfer object (DTO)
10266  * representing the row to delete. @throws TskCoreException
10267  */
10268  public void deleteBlackboardArtifactTag(BlackboardArtifactTag tag) throws TskCoreException {
10269  CaseDbConnection connection = connections.getConnection();
10271  try {
10272  // DELETE FROM blackboard_artifact_tags WHERE tag_id = ?
10273  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_ARTIFACT_TAG);
10274  statement.clearParameters();
10275  statement.setLong(1, tag.getId());
10276  connection.executeUpdate(statement);
10277  } catch (SQLException ex) {
10278  throw new TskCoreException("Error deleting row from blackboard_artifact_tags table (id = " + tag.getId() + ")", ex);
10279  } finally {
10280  connection.close();
10282  }
10283  }
10284 
10294  public List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException {
10295  CaseDbConnection connection = connections.getConnection();
10297  ResultSet resultSet = null;
10298  try {
10299  // 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
10300  // FROM blackboard_artifact_tags
10301  // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
10302  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10303  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS);
10304  resultSet = connection.executeQuery(statement);
10305  ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
10306  while (resultSet.next()) {
10307  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10308  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10309  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
10310  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10311  Content content = getContentById(artifact.getObjectID());
10312  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10313  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10314  tags.add(tag);
10315  }
10316  return tags;
10317  } catch (SQLException ex) {
10318  throw new TskCoreException("Error selecting rows from blackboard_artifact_tags table", ex);
10319  } finally {
10320  closeResultSet(resultSet);
10321  connection.close();
10323  }
10324  }
10325 
10336  public long getBlackboardArtifactTagsCountByTagName(TagName tagName) throws TskCoreException {
10337  if (tagName.getId() == Tag.ID_NOT_SET) {
10338  throw new TskCoreException("TagName object is invalid, id not set");
10339  }
10340  CaseDbConnection connection = connections.getConnection();
10342  ResultSet resultSet = null;
10343  try {
10344  // SELECT COUNT(*) AS count FROM blackboard_artifact_tags WHERE tag_name_id = ?
10345  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_TAG_NAME);
10346  statement.clearParameters();
10347  statement.setLong(1, tagName.getId());
10348  resultSet = connection.executeQuery(statement);
10349  if (resultSet.next()) {
10350  return resultSet.getLong("count");
10351  } else {
10352  throw new TskCoreException("Error getting blackboard_artifact_tags row count for tag name (tag_name_id = " + tagName.getId() + ")");
10353  }
10354  } catch (SQLException ex) {
10355  throw new TskCoreException("Error getting blackboard artifact_content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")", ex);
10356  } finally {
10357  closeResultSet(resultSet);
10358  connection.close();
10360  }
10361  }
10362 
10377  public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10378 
10379  if (tagName.getId() == Tag.ID_NOT_SET) {
10380  throw new TskCoreException("TagName object is invalid, id not set");
10381  }
10382 
10383  CaseDbConnection connection = connections.getConnection();
10385  ResultSet resultSet = null;
10386  try {
10387  // "SELECT COUNT(*) AS count FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts WHERE artifact_tags.artifact_id = arts.artifact_id"
10388  // + " AND artifact_tags.tag_name_id = ?"
10389  // + " AND arts.data_source_obj_id = ? "
10390  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_TAG_NAME_BY_DATASOURCE);
10391  statement.clearParameters();
10392  statement.setLong(1, tagName.getId());
10393  statement.setLong(2, dsObjId);
10394  resultSet = connection.executeQuery(statement);
10395  if (resultSet.next()) {
10396  return resultSet.getLong("count");
10397  } else {
10398  throw new TskCoreException("Error getting blackboard_artifact_tags row count for tag name (tag_name_id = " + tagName.getId() + ")" + " for dsObjId = " + dsObjId);
10399  }
10400  } catch (SQLException ex) {
10401  throw new TskCoreException("Failed to get blackboard_artifact_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
10402  } finally {
10403  closeResultSet(resultSet);
10404  connection.close();
10406  }
10407  }
10408 
10420  public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException {
10421  if (tagName.getId() == Tag.ID_NOT_SET) {
10422  throw new TskCoreException("TagName object is invalid, id not set");
10423  }
10424  CaseDbConnection connection = connections.getConnection();
10426  ResultSet resultSet = null;
10427  try {
10428  // 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
10429  // FROM blackboard_artifact_tags
10430  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10431  // WHERE tag_name_id = ?
10432  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_TAG_NAME);
10433  statement.clearParameters();
10434  statement.setLong(1, tagName.getId());
10435  resultSet = connection.executeQuery(statement);
10436  ArrayList<BlackboardArtifactTag> tags = new ArrayList<BlackboardArtifactTag>();
10437  while (resultSet.next()) {
10438  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10439  Content content = getContentById(artifact.getObjectID());
10440  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10441  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10442  tags.add(tag);
10443  }
10444  return tags;
10445  } catch (SQLException ex) {
10446  throw new TskCoreException("Error getting blackboard artifact tags data (tag_name_id = " + tagName.getId() + ")", ex);
10447  } finally {
10448  closeResultSet(resultSet);
10449  connection.close();
10451  }
10452  }
10453 
10468  public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
10469 
10470  if (tagName.getId() == Tag.ID_NOT_SET) {
10471  throw new TskCoreException("TagName object is invalid, id not set");
10472  }
10473 
10474  CaseDbConnection connection = connections.getConnection();
10476  ResultSet resultSet = null;
10477  try {
10478  // 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
10479  // FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts
10480  // LEFT OUTER JOIN tsk_examiners ON artifact_tags.examiner_id = tsk_examiners.examiner_id
10481  // WHERE artifact_tags.artifact_id = arts.artifact_id
10482  // AND artifact_tags.tag_name_id = ?
10483  // AND arts.data_source_obj_id = ?
10484  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
10485  statement.clearParameters();
10486  statement.setLong(1, tagName.getId());
10487  statement.setLong(2, dsObjId);
10488  resultSet = connection.executeQuery(statement);
10489  ArrayList<BlackboardArtifactTag> tags = new ArrayList<BlackboardArtifactTag>();
10490  while (resultSet.next()) {
10491  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10492  Content content = getContentById(artifact.getObjectID());
10493  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10494  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10495  tags.add(tag);
10496  }
10497  return tags;
10498  } catch (SQLException ex) {
10499  throw new TskCoreException("Failed to get blackboard_artifact_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
10500  } finally {
10501  closeResultSet(resultSet);
10502  connection.close();
10504  }
10505 
10506  }
10507 
10519  public BlackboardArtifactTag getBlackboardArtifactTagByID(long artifactTagID) throws TskCoreException {
10520 
10521  CaseDbConnection connection = connections.getConnection();
10523  ResultSet resultSet = null;
10524  BlackboardArtifactTag tag = null;
10525  try {
10526  //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
10527  // FROM blackboard_artifact_tags
10528  // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
10529  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10530  // WHERE blackboard_artifact_tags.tag_id = ?
10531  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAG_BY_ID);
10532  statement.clearParameters();
10533  statement.setLong(1, artifactTagID);
10534  resultSet = connection.executeQuery(statement);
10535 
10536  while (resultSet.next()) {
10537  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10538  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10539  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
10540  BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
10541  Content content = getContentById(artifact.getObjectID());
10542  tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10543  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name"));
10544  }
10545  resultSet.close();
10546 
10547  } catch (SQLException ex) {
10548  throw new TskCoreException("Error getting blackboard artifact tag with id = " + artifactTagID, ex);
10549  } finally {
10550  closeResultSet(resultSet);
10551  connection.close();
10553  }
10554  return tag;
10555  }
10556 
10569  public List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException {
10570  CaseDbConnection connection = connections.getConnection();
10572  ResultSet resultSet = null;
10573  try {
10574  // 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
10575  // FROM blackboard_artifact_tags
10576  // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
10577  // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
10578  // WHERE blackboard_artifact_tags.artifact_id = ?
10579  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_ARTIFACT);
10580  statement.clearParameters();
10581  statement.setLong(1, artifact.getArtifactID());
10582  resultSet = connection.executeQuery(statement);
10583  ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
10584  while (resultSet.next()) {
10585  TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
10586  resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
10587  TskData.FileKnown.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
10588  Content content = getContentById(artifact.getObjectID());
10589  BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
10590  artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
10591  tags.add(tag);
10592  }
10593  return tags;
10594  } catch (SQLException ex) {
10595  throw new TskCoreException("Error getting blackboard artifact tags data (artifact_id = " + artifact.getArtifactID() + ")", ex);
10596  } finally {
10597  closeResultSet(resultSet);
10598  connection.close();
10600  }
10601  }
10602 
10611  public void updateImagePath(String newPath, long objectId) throws TskCoreException {
10612  CaseDbConnection connection = connections.getConnection();
10614  try {
10615  // UPDATE tsk_image_names SET name = ? WHERE obj_id = ?
10616  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_PATH);
10617  statement.clearParameters();
10618  statement.setString(1, newPath);
10619  statement.setLong(2, objectId);
10620  connection.executeUpdate(statement);
10621  } catch (SQLException ex) {
10622  throw new TskCoreException("Error updating image path in database for object " + objectId, ex);
10623  } finally {
10624  connection.close();
10626  }
10627  }
10628 
10642  public Report addReport(String localPath, String sourceModuleName, String reportName) throws TskCoreException {
10643  return addReport(localPath, sourceModuleName, reportName, null);
10644  }
10645 
10661  public Report addReport(String localPath, String sourceModuleName, String reportName, Content parent) throws TskCoreException {
10662  // Make sure the local path of the report is in the database directory
10663  // or one of its subdirectories.
10664  String relativePath = ""; //NON-NLS
10665  long createTime = 0;
10666  String localPathLower = localPath.toLowerCase();
10667 
10668  if (localPathLower.startsWith("http")) {
10669  relativePath = localPathLower;
10670  createTime = System.currentTimeMillis() / 1000;
10671  } else {
10672  /*
10673  * Note: The following call to .relativize() may be dangerous in
10674  * case-sensitive operating systems and should be looked at. For
10675  * now, we are simply relativizing the paths as all lower case, then
10676  * using the length of the result to pull out the appropriate number
10677  * of characters from the localPath String.
10678  */
10679  try {
10680  String casePathLower = getDbDirPath().toLowerCase();
10681  int length = new File(casePathLower).toURI().relativize(new File(localPathLower).toURI()).getPath().length();
10682  relativePath = new File(localPath.substring(localPathLower.length() - length)).getPath();
10683  } catch (IllegalArgumentException ex) {
10684  String errorMessage = String.format("Local path %s not in the database directory or one of its subdirectories", localPath);
10685  throw new TskCoreException(errorMessage, ex);
10686  }
10687  try {
10688  // get its file time
10689  java.io.File tempFile = new java.io.File(localPath);
10690  // Convert to UNIX epoch (seconds, not milliseconds).
10691  createTime = tempFile.lastModified() / 1000;
10692  } catch (Exception ex) {
10693  throw new TskCoreException("Could not get create time for report at " + localPath, ex);
10694  }
10695  }
10696 
10697  // Write the report data to the database.
10698  CaseDbConnection connection = connections.getConnection();
10700  ResultSet resultSet = null;
10701  try {
10702  // Insert a row for the report into the tsk_objects table.
10703  // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
10704  long parentObjId = 0;
10705  if (parent != null) {
10706  parentObjId = parent.getId();
10707  }
10708  long objectId = addObject(parentObjId, TskData.ObjectType.REPORT.getObjectType(), connection);
10709 
10710  // INSERT INTO reports (obj_id, path, crtime, src_module_name, display_name) VALUES (?, ?, ?, ?, ?)
10711  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_REPORT);
10712  statement.clearParameters();
10713  statement.setLong(1, objectId);
10714  statement.setString(2, relativePath);
10715  statement.setLong(3, createTime);
10716  statement.setString(4, sourceModuleName);
10717  statement.setString(5, reportName);
10718  connection.executeUpdate(statement);
10719  return new Report(this, objectId, localPath, createTime, sourceModuleName, reportName, parent);
10720  } catch (SQLException ex) {
10721  throw new TskCoreException("Error adding report " + localPath + " to reports table", ex);
10722  } finally {
10723  closeResultSet(resultSet);
10724  connection.close();
10726  }
10727  }
10728 
10737  public List<Report> getAllReports() throws TskCoreException {
10738  CaseDbConnection connection = connections.getConnection();
10740  ResultSet resultSet = null;
10741  ResultSet parentResultSet = null;
10742  PreparedStatement statement = null;
10743  Statement parentStatement = null;
10744  try {
10745  // SELECT * FROM reports
10746  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_REPORTS);
10747  parentStatement = connection.createStatement();
10748  resultSet = connection.executeQuery(statement);
10749  ArrayList<Report> reports = new ArrayList<Report>();
10750  while (resultSet.next()) {
10751  String localpath = resultSet.getString("path");
10752  if (localpath.toLowerCase().startsWith("http") == false) {
10753  // make path absolute
10754  localpath = Paths.get(getDbDirPath(), localpath).normalize().toString(); //NON-NLS
10755  }
10756 
10757  // get the report parent
10758  Content parent = null;
10759  long reportId = resultSet.getLong("obj_id"); // NON-NLS
10760  String parentQuery = String.format("SELECT * FROM tsk_objects WHERE obj_id = %s;", reportId);
10761  parentResultSet = parentStatement.executeQuery(parentQuery);
10762  if (parentResultSet.next()) {
10763  long parentId = parentResultSet.getLong("par_obj_id"); // NON-NLS
10764  parent = this.getContentById(parentId);
10765  }
10766  parentResultSet.close();
10767 
10768  reports.add(new Report(this,
10769  reportId,
10770  localpath,
10771  resultSet.getLong("crtime"), //NON-NLS
10772  resultSet.getString("src_module_name"), //NON-NLS
10773  resultSet.getString("report_name"),
10774  parent)); //NON-NLS
10775  }
10776  return reports;
10777  } catch (SQLException ex) {
10778  throw new TskCoreException("Error querying reports table", ex);
10779  } finally {
10780  closeResultSet(resultSet);
10781  closeResultSet(parentResultSet);
10782  closeStatement(statement);
10783  closeStatement(parentStatement);
10784 
10785  connection.close();
10787  }
10788  }
10789 
10799  public Report getReportById(long id) throws TskCoreException {
10800  CaseDbConnection connection = connections.getConnection();
10802  PreparedStatement statement = null;
10803  Statement parentStatement = null;
10804  ResultSet resultSet = null;
10805  ResultSet parentResultSet = null;
10806  Report report = null;
10807  try {
10808  // SELECT * FROM reports WHERE obj_id = ?
10809  statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_REPORT_BY_ID);
10810  parentStatement = connection.createStatement();
10811  statement.clearParameters();
10812  statement.setLong(1, id);
10813  resultSet = connection.executeQuery(statement);
10814 
10815  if (resultSet.next()) {
10816  // get the report parent
10817  Content parent = null;
10818  String parentQuery = String.format("SELECT * FROM tsk_objects WHERE obj_id = %s;", id);
10819  parentResultSet = parentStatement.executeQuery(parentQuery);
10820  if (parentResultSet.next()) {
10821  long parentId = parentResultSet.getLong("par_obj_id"); // NON-NLS
10822  parent = this.getContentById(parentId);
10823  }
10824 
10825  report = new Report(this, resultSet.getLong("obj_id"), //NON-NLS
10826  Paths.get(getDbDirPath(), resultSet.getString("path")).normalize().toString(), //NON-NLS
10827  resultSet.getLong("crtime"), //NON-NLS
10828  resultSet.getString("src_module_name"), //NON-NLS
10829  resultSet.getString("report_name"),
10830  parent); //NON-NLS
10831  } else {
10832  throw new TskCoreException("No report found for id: " + id);
10833  }
10834  } catch (SQLException ex) {
10835  throw new TskCoreException("Error querying reports table for id: " + id, ex);
10836  } finally {
10837  closeResultSet(resultSet);
10838  closeResultSet(parentResultSet);
10839  closeStatement(statement);
10840  closeStatement(parentStatement);
10841  connection.close();
10843  }
10844 
10845  return report;
10846  }
10847 
10855  public void deleteReport(Report report) throws TskCoreException {
10856  CaseDbConnection connection = connections.getConnection();
10858  try {
10859  // DELETE FROM reports WHERE reports.obj_id = ?
10860  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_REPORT);
10861  statement.setLong(1, report.getId());
10862  connection.executeUpdate(statement);
10863  } catch (SQLException ex) {
10864  throw new TskCoreException("Error querying reports table", ex);
10865  } finally {
10866  connection.close();
10868  }
10869  }
10870 
10871  static void closeResultSet(ResultSet resultSet) {
10872  if (resultSet != null) {
10873  try {
10874  resultSet.close();
10875  } catch (SQLException ex) {
10876  logger.log(Level.SEVERE, "Error closing ResultSet", ex); //NON-NLS
10877  }
10878  }
10879  }
10880 
10881  static void closeStatement(Statement statement) {
10882  if (statement != null) {
10883  try {
10884  statement.close();
10885  } catch (SQLException ex) {
10886  logger.log(Level.SEVERE, "Error closing Statement", ex); //NON-NLS
10887 
10888  }
10889  }
10890  }
10891 
10900  void setIngestJobEndDateTime(long ingestJobId, long endDateTime) throws TskCoreException {
10901  CaseDbConnection connection = connections.getConnection();
10903  try {
10904  Statement statement = connection.createStatement();
10905  statement.executeUpdate("UPDATE ingest_jobs SET end_date_time=" + endDateTime + " WHERE ingest_job_id=" + ingestJobId + ";");
10906  } catch (SQLException ex) {
10907  throw new TskCoreException("Error updating the end date (ingest_job_id = " + ingestJobId + ".", ex);
10908  } finally {
10909  connection.close();
10911  }
10912  }
10913 
10914  void setIngestJobStatus(long ingestJobId, IngestJobStatusType status) throws TskCoreException {
10915  CaseDbConnection connection = connections.getConnection();
10917  try {
10918  Statement statement = connection.createStatement();
10919  statement.executeUpdate("UPDATE ingest_jobs SET status_id=" + status.ordinal() + " WHERE ingest_job_id=" + ingestJobId + ";");
10920  } catch (SQLException ex) {
10921  throw new TskCoreException("Error ingest job status (ingest_job_id = " + ingestJobId + ".", ex);
10922  } finally {
10923  connection.close();
10925  }
10926  }
10927 
10944  public final IngestJobInfo addIngestJob(Content dataSource, String hostName, List<IngestModuleInfo> ingestModules, Date jobStart, Date jobEnd, IngestJobStatusType status, String settingsDir) throws TskCoreException {
10945  CaseDbConnection connection = connections.getConnection();
10947  ResultSet resultSet = null;
10948  Statement statement;
10949  try {
10950  connection.beginTransaction();
10951  statement = connection.createStatement();
10952  PreparedStatement insertStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INGEST_JOB, Statement.RETURN_GENERATED_KEYS);
10953  insertStatement.setLong(1, dataSource.getId());
10954  insertStatement.setString(2, hostName);
10955  insertStatement.setLong(3, jobStart.getTime());
10956  insertStatement.setLong(4, jobEnd.getTime());
10957  insertStatement.setInt(5, status.ordinal());
10958  insertStatement.setString(6, settingsDir);
10959  connection.executeUpdate(insertStatement);
10960  resultSet = insertStatement.getGeneratedKeys();
10961  resultSet.next();
10962  long id = resultSet.getLong(1); //last_insert_rowid()
10963  for (int i = 0; i < ingestModules.size(); i++) {
10964  IngestModuleInfo ingestModule = ingestModules.get(i);
10965  statement.executeUpdate("INSERT INTO ingest_job_modules (ingest_job_id, ingest_module_id, pipeline_position) "
10966  + "VALUES (" + id + ", " + ingestModule.getIngestModuleId() + ", " + i + ");");
10967  }
10968  resultSet.close();
10969  resultSet = null;
10970  connection.commitTransaction();
10971  return new IngestJobInfo(id, dataSource.getId(), hostName, jobStart, "", ingestModules, this);
10972  } catch (SQLException ex) {
10973  connection.rollbackTransaction();
10974  throw new TskCoreException("Error adding the ingest job.", ex);
10975  } finally {
10976  closeResultSet(resultSet);
10977  connection.close();
10979  }
10980  }
10981 
10995  public final IngestModuleInfo addIngestModule(String displayName, String factoryClassName, IngestModuleType type, String version) throws TskCoreException {
10996  CaseDbConnection connection = connections.getConnection();
10997  ResultSet resultSet = null;
10998  Statement statement = null;
10999  String uniqueName = factoryClassName + "-" + displayName + "-" + type.toString() + "-" + version;
11001  try {
11002  statement = connection.createStatement();
11003  resultSet = statement.executeQuery("SELECT * FROM ingest_modules WHERE unique_name = '" + uniqueName + "'");
11004  if (!resultSet.next()) {
11005  resultSet.close();
11006  resultSet = null;
11007  PreparedStatement insertStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INGEST_MODULE, Statement.RETURN_GENERATED_KEYS);
11008  insertStatement.setString(1, displayName);
11009  insertStatement.setString(2, uniqueName);
11010  insertStatement.setInt(3, type.ordinal());
11011  insertStatement.setString(4, version);
11012  connection.executeUpdate(insertStatement);
11013  resultSet = statement.getGeneratedKeys();
11014  resultSet.next();
11015  long id = resultSet.getLong(1); //last_insert_rowid()
11016  resultSet.close();
11017  resultSet = null;
11018  return new IngestModuleInfo(id, displayName, uniqueName, type, version);
11019  } else {
11020  return new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
11021  resultSet.getString("unique_name"), IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version"));
11022  }
11023  } catch (SQLException ex) {
11024  try {
11025  closeStatement(statement);
11026  statement = connection.createStatement();
11027  resultSet = statement.executeQuery("SELECT * FROM ingest_modules WHERE unique_name = '" + uniqueName + "'");
11028  if (resultSet.next()) {
11029  return new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
11030  uniqueName, IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version"));
11031  } else {
11032  throw new TskCoreException("Couldn't add new module to database.", ex);
11033  }
11034  } catch (SQLException ex1) {
11035  throw new TskCoreException("Couldn't add new module to database.", ex1);
11036  }
11037  } finally {
11038  closeResultSet(resultSet);
11039  closeStatement(statement);
11040  connection.close();
11042  }
11043  }
11044 
11052  public final List<IngestJobInfo> getIngestJobs() throws TskCoreException {
11053  CaseDbConnection connection = connections.getConnection();
11054  ResultSet resultSet = null;
11055  Statement statement = null;
11056  List<IngestJobInfo> ingestJobs = new ArrayList<IngestJobInfo>();
11058  try {
11059  statement = connection.createStatement();
11060  resultSet = statement.executeQuery("SELECT * FROM ingest_jobs");
11061  while (resultSet.next()) {
11062  ingestJobs.add(new IngestJobInfo(resultSet.getInt("ingest_job_id"), resultSet.getLong("obj_id"),
11063  resultSet.getString("host_name"), new Date(resultSet.getLong("start_date_time")),
11064  new Date(resultSet.getLong("end_date_time")), IngestJobStatusType.fromID(resultSet.getInt("status_id")),
11065  resultSet.getString("settings_dir"), this.getIngestModules(resultSet.getInt("ingest_job_id"), connection), this));
11066  }
11067  return ingestJobs;
11068  } catch (SQLException ex) {
11069  throw new TskCoreException("Couldn't get the ingest jobs.", ex);
11070  } finally {
11071  closeResultSet(resultSet);
11072  closeStatement(statement);
11073  connection.close();
11075  }
11076  }
11077 
11088  private List<IngestModuleInfo> getIngestModules(int ingestJobId, CaseDbConnection connection) throws SQLException {
11089  ResultSet resultSet = null;
11090  Statement statement = null;
11091  List<IngestModuleInfo> ingestModules = new ArrayList<IngestModuleInfo>();
11093  try {
11094  statement = connection.createStatement();
11095  resultSet = statement.executeQuery("SELECT ingest_job_modules.ingest_module_id AS ingest_module_id, "
11096  + "ingest_job_modules.pipeline_position AS pipeline_position, "
11097  + "ingest_modules.display_name AS display_name, ingest_modules.unique_name AS unique_name, "
11098  + "ingest_modules.type_id AS type_id, ingest_modules.version AS version "
11099  + "FROM ingest_job_modules, ingest_modules "
11100  + "WHERE ingest_job_modules.ingest_job_id = " + ingestJobId + " "
11101  + "AND ingest_modules.ingest_module_id = ingest_job_modules.ingest_module_id "
11102  + "ORDER BY (ingest_job_modules.pipeline_position);");
11103  while (resultSet.next()) {
11104  ingestModules.add(new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
11105  resultSet.getString("unique_name"), IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version")));
11106  }
11107  return ingestModules;
11108  } finally {
11109  closeResultSet(resultSet);
11110  closeStatement(statement);
11112 
11113  }
11114  }
11115 
11119  static class ObjectInfo {
11120 
11121  private long id;
11122  private TskData.ObjectType type;
11123 
11124  ObjectInfo(long id, ObjectType type) {
11125  this.id = id;
11126  this.type = type;
11127  }
11128 
11129  long getId() {
11130  return id;
11131  }
11132 
11133  TskData.ObjectType getType() {
11134  return type;
11135  }
11136  }
11137 
11138  private interface DbCommand {
11139 
11140  void execute() throws SQLException;
11141  }
11142 
11143  private enum PREPARED_STATEMENT {
11144 
11145  SELECT_ARTIFACTS_BY_TYPE("SELECT artifact_id, obj_id FROM blackboard_artifacts " //NON-NLS
11146  + "WHERE artifact_type_id = ?"), //NON-NLS
11147  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
11148  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
11149  COUNT_ARTIFACTS_FROM_SOURCE("SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()), //NON-NLS
11150  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
11151  SELECT_FILES_BY_PARENT("SELECT tsk_files.* " //NON-NLS
11152  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11153  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11154  + "WHERE (tsk_objects.par_obj_id = ? ) " //NON-NLS
11155  + "ORDER BY tsk_files.meta_type DESC, LOWER(tsk_files.name)"), //NON-NLS
11156  SELECT_FILES_BY_PARENT_AND_TYPE("SELECT tsk_files.* " //NON-NLS
11157  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11158  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11159  + "WHERE (tsk_objects.par_obj_id = ? AND tsk_files.type = ? ) " //NON-NLS
11160  + "ORDER BY tsk_files.dir_type, LOWER(tsk_files.name)"), //NON-NLS
11161  SELECT_FILE_IDS_BY_PARENT("SELECT tsk_files.obj_id AS obj_id " //NON-NLS
11162  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11163  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11164  + "WHERE (tsk_objects.par_obj_id = ?)"), //NON-NLS
11165  SELECT_FILE_IDS_BY_PARENT_AND_TYPE("SELECT tsk_files.obj_id AS obj_id " //NON-NLS
11166  + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
11167  + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
11168  + "WHERE (tsk_objects.par_obj_id = ? " //NON-NLS
11169  + "AND tsk_files.type = ? )"), //NON-NLS
11170  SELECT_FILE_BY_ID("SELECT * FROM tsk_files WHERE obj_id = ? LIMIT 1"), //NON-NLS
11171  SELECT_ARTIFACT_BY_ARTIFACT_OBJ_ID("SELECT * FROM blackboard_artifacts WHERE artifact_obj_id = ? LIMIT 1"),
11172  SELECT_ARTIFACT_BY_ARTIFACT_ID("SELECT * FROM blackboard_artifacts WHERE artifact_id = ? LIMIT 1"),
11173  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
11174  + "VALUES (?, ?, ?, ?, ?," + BlackboardArtifact.ReviewStatus.UNDECIDED.getID() + ")"), //NON-NLS
11175  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
11176  + "VALUES (DEFAULT, ?, ?, ?, ?," + BlackboardArtifact.ReviewStatus.UNDECIDED.getID() + ")"), //NON-NLS
11177  INSERT_STRING_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_text) " //NON-NLS
11178  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11179  INSERT_BYTE_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_byte) " //NON-NLS
11180  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11181  INSERT_INT_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_int32) " //NON-NLS
11182  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11183  INSERT_LONG_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_int64) " //NON-NLS
11184  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11185  INSERT_DOUBLE_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_double) " //NON-NLS
11186  + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
11187  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
11188  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
11189  UPDATE_FILE_MD5("UPDATE tsk_files SET md5 = ? WHERE obj_id = ?"), //NON-NLS
11190  UPDATE_IMAGE_MD5("UPDATE tsk_image_info SET md5 = ? WHERE obj_id = ?"), //NON-NLS
11191  UPDATE_IMAGE_SHA1("UPDATE tsk_image_info SET sha1 = ? WHERE obj_id = ?"), //NON-NLS
11192  UPDATE_IMAGE_SHA256("UPDATE tsk_image_info SET sha256 = ? WHERE obj_id = ?"), //NON-NLS
11193  SELECT_IMAGE_MD5("SELECT md5 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
11194  SELECT_IMAGE_SHA1("SELECT sha1 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
11195  SELECT_IMAGE_SHA256("SELECT sha256 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
11196  UPDATE_ACQUISITION_DETAILS("UPDATE data_source_info SET acquisition_details = ? WHERE obj_id = ?"), //NON-NLS
11197  SELECT_ACQUISITION_DETAILS("SELECT acquisition_details FROM data_source_info WHERE obj_id = ?"), //NON-NLS
11198  SELECT_LOCAL_PATH_FOR_FILE("SELECT path FROM tsk_files_path WHERE obj_id = ?"), //NON-NLS
11199  SELECT_ENCODING_FOR_FILE("SELECT encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON-NLS
11200  SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE("SELECT path, encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON_NLS
11201  SELECT_PATH_FOR_FILE("SELECT parent_path FROM tsk_files WHERE obj_id = ?"), //NON-NLS
11202  SELECT_FILE_NAME("SELECT name FROM tsk_files WHERE obj_id = ?"), //NON-NLS
11203  SELECT_DERIVED_FILE("SELECT derived_id, rederive FROM tsk_files_derived WHERE obj_id = ?"), //NON-NLS
11204  SELECT_FILE_DERIVATION_METHOD("SELECT tool_name, tool_version, other FROM tsk_files_derived_method WHERE derived_id = ?"), //NON-NLS
11205  SELECT_MAX_OBJECT_ID("SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects"), //NON-NLS
11206  INSERT_OBJECT("INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)"), //NON-NLS
11207  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, sha256, known, mime_type, parent_path, data_source_obj_id,extension) " //NON-NLS
11208  + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), //NON-NLS
11209  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)"
11210  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), // NON-NLS
11211  UPDATE_DERIVED_FILE("UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? "
11212  + "WHERE obj_id = ?"), //NON-NLS
11213  INSERT_LAYOUT_FILE("INSERT INTO tsk_file_layout (obj_id, byte_start, byte_len, sequence) " //NON-NLS
11214  + "VALUES (?, ?, ?, ?)"), //NON-NLS
11215  INSERT_LOCAL_PATH("INSERT INTO tsk_files_path (obj_id, path, encoding_type) VALUES (?, ?, ?)"), //NON-NLS
11216  UPDATE_LOCAL_PATH("UPDATE tsk_files_path SET path = ?, encoding_type = ? WHERE obj_id = ?"), //NON-NLS
11217  COUNT_CHILD_OBJECTS_BY_PARENT("SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?"), //NON-NLS
11218  SELECT_FILE_SYSTEM_BY_OBJECT("SELECT fs_obj_id from tsk_files WHERE obj_id=?"), //NON-NLS
11219  SELECT_TAG_NAMES("SELECT * FROM tag_names"), //NON-NLS
11220  SELECT_TAG_NAMES_IN_USE("SELECT * FROM tag_names " //NON-NLS
11221  + "WHERE tag_name_id IN " //NON-NLS
11222  + "(SELECT tag_name_id from content_tags UNION SELECT tag_name_id FROM blackboard_artifact_tags)"), //NON-NLS
11223  SELECT_TAG_NAMES_IN_USE_BY_DATASOURCE("SELECT * FROM tag_names "
11224  + "WHERE tag_name_id IN "
11225  + "( SELECT content_tags.tag_name_id as tag_name_id "
11226  + "FROM content_tags as content_tags, tsk_files as tsk_files"
11227  + " WHERE content_tags.obj_id = tsk_files.obj_id"
11228  + " AND tsk_files.data_source_obj_id = ?"
11229  + " UNION "
11230  + "SELECT artifact_tags.tag_name_id as tag_name_id "
11231  + " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts "
11232  + " WHERE artifact_tags.artifact_id = arts.artifact_id"
11233  + " AND arts.data_source_obj_id = ?"
11234  + " )"),
11235  INSERT_TAG_NAME("INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?)"), //NON-NLS
11236  INSERT_CONTENT_TAG("INSERT INTO content_tags (obj_id, tag_name_id, comment, begin_byte_offset, end_byte_offset, examiner_id) VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
11237  DELETE_CONTENT_TAG("DELETE FROM content_tags WHERE tag_id = ?"), //NON-NLS
11238  COUNT_CONTENT_TAGS_BY_TAG_NAME("SELECT COUNT(*) AS count FROM content_tags WHERE tag_name_id = ?"), //NON-NLS
11239  COUNT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE(
11240  "SELECT COUNT(*) AS count FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id"
11241  + " AND content_tags.tag_name_id = ? "
11242  + " AND tsk_files.data_source_obj_id = ? "
11243  ),
11244  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 "
11245  + "FROM content_tags "
11246  + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
11247  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS
11248  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 "
11249  + "FROM content_tags "
11250  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
11251  + "WHERE tag_name_id = ?"), //NON-NLS
11252  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 "
11253  + "FROM content_tags as content_tags, tsk_files as tsk_files, tag_names as tag_names, tsk_examiners as tsk_examiners "
11254  + "WHERE content_tags.examiner_id = tsk_examiners.examiner_id"
11255  + " AND content_tags.obj_id = tsk_files.obj_id"
11256  + " AND content_tags.tag_name_id = tag_names.tag_name_id"
11257  + " AND content_tags.tag_name_id = ?"
11258  + " AND tsk_files.data_source_obj_id = ? "),
11259  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 "
11260  + "FROM content_tags "
11261  + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
11262  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
11263  + "WHERE tag_id = ?"), //NON-NLS
11264  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 "
11265  + "FROM content_tags "
11266  + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
11267  + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
11268  + "WHERE content_tags.obj_id = ?"), //NON-NLS
11269  INSERT_ARTIFACT_TAG("INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment, examiner_id) "
11270  + "VALUES (?, ?, ?, ?)"), //NON-NLS
11271  DELETE_ARTIFACT_TAG("DELETE FROM blackboard_artifact_tags WHERE tag_id = ?"), //NON-NLS
11272  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 "
11273  + "FROM blackboard_artifact_tags "
11274  + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
11275  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS
11276  COUNT_ARTIFACTS_BY_TAG_NAME("SELECT COUNT(*) AS count FROM blackboard_artifact_tags WHERE tag_name_id = ?"), //NON-NLS
11277  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"
11278  + " AND artifact_tags.tag_name_id = ?"
11279  + " AND arts.data_source_obj_id = ? "),
11280  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 "
11281  + "FROM blackboard_artifact_tags "
11282  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
11283  + "WHERE tag_name_id = ?"), //NON-NLS
11284  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 "
11285  + "FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts, tsk_examiners AS tsk_examiners "
11286  + "WHERE artifact_tags.examiner_id = tsk_examiners.examiner_id"
11287  + " AND artifact_tags.artifact_id = arts.artifact_id"
11288  + " AND artifact_tags.tag_name_id = ? "
11289  + " AND arts.data_source_obj_id = ? "),
11290  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 "
11291  + "FROM blackboard_artifact_tags "
11292  + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
11293  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
11294  + "WHERE blackboard_artifact_tags.tag_id = ?"), //NON-NLS
11295  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 "
11296  + "FROM blackboard_artifact_tags "
11297  + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
11298  + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
11299  + "WHERE blackboard_artifact_tags.artifact_id = ?"), //NON-NLS
11300  SELECT_REPORTS("SELECT * FROM reports"), //NON-NLS
11301  SELECT_REPORT_BY_ID("SELECT * FROM reports WHERE obj_id = ?"), //NON-NLS
11302  INSERT_REPORT("INSERT INTO reports (obj_id, path, crtime, src_module_name, report_name) VALUES (?, ?, ?, ?, ?)"), //NON-NLS
11303  DELETE_REPORT("DELETE FROM reports WHERE reports.obj_id = ?"), //NON-NLS
11304  INSERT_INGEST_JOB("INSERT INTO ingest_jobs (obj_id, host_name, start_date_time, end_date_time, status_id, settings_dir) VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
11305  INSERT_INGEST_MODULE("INSERT INTO ingest_modules (display_name, unique_name, type_id, version) VALUES(?, ?, ?, ?)"), //NON-NLS
11306  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
11307  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
11308  UPDATE_IMAGE_PATH("UPDATE tsk_image_names SET name = ? WHERE obj_id = ?"), // NON-NLS
11309  SELECT_ARTIFACT_OBJECTIDS_BY_PARENT("SELECT blackboard_artifacts.artifact_obj_id AS artifact_obj_id " //NON-NLS
11310  + "FROM tsk_objects INNER JOIN blackboard_artifacts " //NON-NLS
11311  + "ON tsk_objects.obj_id=blackboard_artifacts.obj_id " //NON-NLS
11312  + "WHERE (tsk_objects.par_obj_id = ?)"),
11313  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 = ?"),
11314  SELECT_EXAMINER_BY_ID("SELECT * FROM tsk_examiners WHERE examiner_id = ?"),
11315  SELECT_EXAMINER_BY_LOGIN_NAME("SELECT * FROM tsk_examiners WHERE login_name = ?"),
11316  INSERT_EXAMINER_POSTGRESQL("INSERT INTO tsk_examiners (login_name) VALUES (?) ON CONFLICT DO NOTHING"),
11317  INSERT_EXAMINER_SQLITE("INSERT OR IGNORE INTO tsk_examiners (login_name) VALUES (?)"),
11318  UPDATE_FILE_NAME("UPDATE tsk_files SET name = ? WHERE obj_id = ?"),
11319  UPDATE_IMAGE_NAME("UPDATE tsk_image_info SET display_name = ? WHERE obj_id = ?"),
11320  DELETE_IMAGE_NAME("DELETE FROM tsk_image_names WHERE obj_id = ?"),
11321  INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"),
11322  INSERT_IMAGE_INFO("INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)"
11323  + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"),
11324  INSERT_DATA_SOURCE_INFO("INSERT INTO data_source_info (obj_id, device_id, time_zone) VALUES (?, ?, ?)"),
11325  INSERT_VS_INFO("INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (?, ?, ?, ?)"),
11326  INSERT_VS_PART_SQLITE("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags) VALUES (?, ?, ?, ?, ?, ?)"),
11327  INSERT_VS_PART_POSTGRESQL("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, descr, flags) VALUES (?, ?, ?, ?, ?, ?)"),
11328  INSERT_POOL_INFO("INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)"),
11329  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)"
11330  + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"),
11331  SELECT_TAG_NAME_BY_ID("SELECT * FROM tag_names where tag_name_id = ?"),
11332  SELECT_TAG_NAME_BY_NAME("SELECT * FROM tag_names where display_name = ?");
11333 
11334  private final String sql;
11335 
11336  private PREPARED_STATEMENT(String sql) {
11337  this.sql = sql;
11338  }
11339 
11340  String getSQL() {
11341  return sql;
11342  }
11343  }
11344 
11350  abstract private class ConnectionPool {
11351 
11352  private PooledDataSource pooledDataSource;
11353 
11354  public ConnectionPool() {
11355  pooledDataSource = null;
11356  }
11357 
11358  CaseDbConnection getConnection() throws TskCoreException {
11359  if (pooledDataSource == null) {
11360  throw new TskCoreException("Error getting case database connection - case is closed");
11361  }
11362  try {
11363  return getPooledConnection();
11364  } catch (SQLException exp) {
11365  throw new TskCoreException(exp.getMessage());
11366  }
11367  }
11368 
11369  void close() throws TskCoreException {
11370  if (pooledDataSource != null) {
11371  try {
11372  pooledDataSource.close();
11373  } catch (SQLException exp) {
11374  throw new TskCoreException(exp.getMessage());
11375  } finally {
11376  pooledDataSource = null;
11377  }
11378  }
11379  }
11380 
11381  abstract CaseDbConnection getPooledConnection() throws SQLException;
11382 
11383  public PooledDataSource getPooledDataSource() {
11384  return pooledDataSource;
11385  }
11386 
11387  public void setPooledDataSource(PooledDataSource pooledDataSource) {
11388  this.pooledDataSource = pooledDataSource;
11389  }
11390  }
11391 
11396  private final class SQLiteConnections extends ConnectionPool {
11397 
11398  private final Map<String, String> configurationOverrides = new HashMap<String, String>();
11399 
11400  SQLiteConnections(String dbPath) throws SQLException {
11401  configurationOverrides.put("acquireIncrement", "2");
11402  configurationOverrides.put("initialPoolSize", "5");
11403  configurationOverrides.put("minPoolSize", "5");
11404  /*
11405  * NOTE: max pool size and max statements are related. If you
11406  * increase max pool size, then also increase statements.
11407  */
11408  configurationOverrides.put("maxPoolSize", "20");
11409  configurationOverrides.put("maxStatements", "200");
11410  configurationOverrides.put("maxStatementsPerConnection", "20");
11411 
11412  SQLiteConfig config = new SQLiteConfig();
11413  config.setSynchronous(SQLiteConfig.SynchronousMode.OFF); // Reduce I/O operations, we have no OS crash recovery anyway.
11414  config.setReadUncommited(true);
11415  config.enforceForeignKeys(true); // Enforce foreign key constraints.
11416  SQLiteDataSource unpooled = new SQLiteDataSource(config);
11417  unpooled.setUrl("jdbc:sqlite:" + dbPath);
11418  setPooledDataSource((PooledDataSource) DataSources.pooledDataSource(unpooled, configurationOverrides));
11419  }
11420 
11421  @Override
11422  public CaseDbConnection getPooledConnection() throws SQLException {
11423  return new SQLiteConnection(getPooledDataSource().getConnection());
11424  }
11425  }
11426 
11431  private final class PostgreSQLConnections extends ConnectionPool {
11432 
11433  PostgreSQLConnections(String host, int port, String dbName, String userName, String password) throws PropertyVetoException, UnsupportedEncodingException {
11434  ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
11435  comboPooledDataSource.setDriverClass("org.postgresql.Driver"); //loads the jdbc driver
11436  comboPooledDataSource.setJdbcUrl("jdbc:postgresql://" + host + ":" + port + "/"
11437  + URLEncoder.encode(dbName, StandardCharsets.UTF_8.toString()));
11438  comboPooledDataSource.setUser(userName);
11439  comboPooledDataSource.setPassword(password);
11440  comboPooledDataSource.setAcquireIncrement(2);
11441  comboPooledDataSource.setInitialPoolSize(5);
11442  comboPooledDataSource.setMinPoolSize(5);
11443  /*
11444  * NOTE: max pool size and max statements are related. If you
11445  * increase max pool size, then also increase statements.
11446  */
11447  comboPooledDataSource.setMaxPoolSize(20);
11448  comboPooledDataSource.setMaxStatements(200);
11449  comboPooledDataSource.setMaxStatementsPerConnection(20);
11450  setPooledDataSource(comboPooledDataSource);
11451  }
11452 
11453  @Override
11454  public CaseDbConnection getPooledConnection() throws SQLException {
11455  return new PostgreSQLConnection(getPooledDataSource().getConnection());
11456  }
11457  }
11458 
11462  abstract class CaseDbConnection implements AutoCloseable {
11463 
11464  static final int SLEEP_LENGTH_IN_MILLISECONDS = 5000;
11465  static final int MAX_RETRIES = 20; //MAX_RETRIES * SLEEP_LENGTH_IN_MILLESECONDS = max time to hang attempting connection
11466 
11467  private class CreateStatement implements DbCommand {
11468 
11469  private final Connection connection;
11470  private Statement statement = null;
11471 
11472  CreateStatement(Connection connection) {
11473  this.connection = connection;
11474  }
11475 
11476  Statement getStatement() {
11477  return statement;
11478  }
11479 
11480  @Override
11481  public void execute() throws SQLException {
11482  statement = connection.createStatement();
11483  }
11484  }
11485 
11486  private class SetAutoCommit implements DbCommand {
11487 
11488  private final Connection connection;
11489  private final boolean mode;
11490 
11491  SetAutoCommit(Connection connection, boolean mode) {
11492  this.connection = connection;
11493  this.mode = mode;
11494  }
11495 
11496  @Override
11497  public void execute() throws SQLException {
11498  connection.setAutoCommit(mode);
11499  }
11500  }
11501 
11502  private class Commit implements DbCommand {
11503 
11504  private final Connection connection;
11505 
11506  Commit(Connection connection) {
11507  this.connection = connection;
11508  }
11509 
11510  @Override
11511  public void execute() throws SQLException {
11512  connection.commit();
11513  }
11514  }
11515 
11516  private class ExecuteQuery implements DbCommand {
11517 
11518  private final Statement statement;
11519  private final String query;
11520  private ResultSet resultSet;
11521 
11522  ExecuteQuery(Statement statement, String query) {
11523  this.statement = statement;
11524  this.query = query;
11525  }
11526 
11527  ResultSet getResultSet() {
11528  return resultSet;
11529  }
11530 
11531  @Override
11532  public void execute() throws SQLException {
11533  resultSet = statement.executeQuery(query);
11534  }
11535  }
11536 
11537  private class ExecutePreparedStatementQuery implements DbCommand {
11538 
11539  private final PreparedStatement preparedStatement;
11540  private ResultSet resultSet;
11541 
11542  ExecutePreparedStatementQuery(PreparedStatement preparedStatement) {
11543  this.preparedStatement = preparedStatement;
11544  }
11545 
11546  ResultSet getResultSet() {
11547  return resultSet;
11548  }
11549 
11550  @Override
11551  public void execute() throws SQLException {
11552  resultSet = preparedStatement.executeQuery();
11553  }
11554  }
11555 
11556  private class ExecutePreparedStatementUpdate implements DbCommand {
11557 
11558  private final PreparedStatement preparedStatement;
11559 
11560  ExecutePreparedStatementUpdate(PreparedStatement preparedStatement) {
11561  this.preparedStatement = preparedStatement;
11562  }
11563 
11564  @Override
11565  public void execute() throws SQLException {
11566  preparedStatement.executeUpdate();
11567  }
11568  }
11569 
11570  private class ExecuteStatementUpdate implements DbCommand {
11571 
11572  private final Statement statement;
11573  private final String updateCommand;
11574 
11575  ExecuteStatementUpdate(Statement statement, String updateCommand) {
11576  this.statement = statement;
11577  this.updateCommand = updateCommand;
11578  }
11579 
11580  @Override
11581  public void execute() throws SQLException {
11582  statement.executeUpdate(updateCommand);
11583  }
11584  }
11585 
11586  private class ExecuteStatementUpdateGenerateKeys implements DbCommand {
11587 
11588  private final Statement statement;
11589  private final int generateKeys;
11590  private final String updateCommand;
11591 
11592  ExecuteStatementUpdateGenerateKeys(Statement statement, String updateCommand, int generateKeys) {
11593  this.statement = statement;
11594  this.generateKeys = generateKeys;
11595  this.updateCommand = updateCommand;
11596  }
11597 
11598  @Override
11599  public void execute() throws SQLException {
11600  statement.executeUpdate(updateCommand, generateKeys);
11601  }
11602  }
11603 
11604  private class PrepareStatement implements DbCommand {
11605 
11606  private final Connection connection;
11607  private final String input;
11608  private PreparedStatement preparedStatement = null;
11609 
11610  PrepareStatement(Connection connection, String input) {
11611  this.connection = connection;
11612  this.input = input;
11613  }
11614 
11615  PreparedStatement getPreparedStatement() {
11616  return preparedStatement;
11617  }
11618 
11619  @Override
11620  public void execute() throws SQLException {
11621  preparedStatement = connection.prepareStatement(input);
11622  }
11623  }
11624 
11625  private class PrepareStatementGenerateKeys implements DbCommand {
11626 
11627  private final Connection connection;
11628  private final String input;
11629  private final int generateKeys;
11630  private PreparedStatement preparedStatement = null;
11631 
11632  PrepareStatementGenerateKeys(Connection connection, String input, int generateKeysInput) {
11633  this.connection = connection;
11634  this.input = input;
11635  this.generateKeys = generateKeysInput;
11636  }
11637 
11638  PreparedStatement getPreparedStatement() {
11639  return preparedStatement;
11640  }
11641 
11642  @Override
11643  public void execute() throws SQLException {
11644  preparedStatement = connection.prepareStatement(input, generateKeys);
11645  }
11646  }
11647 
11648  abstract void executeCommand(DbCommand command) throws SQLException;
11649 
11650  private final Connection connection;
11651  private final Map<PREPARED_STATEMENT, PreparedStatement> preparedStatements;
11652  private final Map<String, PreparedStatement> adHocPreparedStatements;
11653 
11654  CaseDbConnection(Connection connection) {
11655  this.connection = connection;
11656  preparedStatements = new EnumMap<PREPARED_STATEMENT, PreparedStatement>(PREPARED_STATEMENT.class);
11657  adHocPreparedStatements = new HashMap<>();
11658  }
11659 
11660  boolean isOpen() {
11661  return this.connection != null;
11662  }
11663 
11664  PreparedStatement getPreparedStatement(PREPARED_STATEMENT statementKey) throws SQLException {
11665  return getPreparedStatement(statementKey, Statement.NO_GENERATED_KEYS);
11666  }
11667 
11668  PreparedStatement getPreparedStatement(PREPARED_STATEMENT statementKey, int generateKeys) throws SQLException {
11669  // Lazy statement preparation.
11670  PreparedStatement statement;
11671  if (this.preparedStatements.containsKey(statementKey)) {
11672  statement = this.preparedStatements.get(statementKey);
11673  } else {
11674  statement = prepareStatement(statementKey.getSQL(), generateKeys);
11675  this.preparedStatements.put(statementKey, statement);
11676  }
11677  return statement;
11678  }
11679 
11691  PreparedStatement getPreparedStatement(String sqlStatement, int generateKeys) throws SQLException {
11692  PreparedStatement statement;
11693  String statementKey = "SQL:" + sqlStatement + " Key:" + generateKeys;
11694  if (adHocPreparedStatements.containsKey(statementKey)) {
11695  statement = this.adHocPreparedStatements.get(statementKey);
11696  } else {
11697  statement = prepareStatement(sqlStatement, generateKeys);
11698  this.adHocPreparedStatements.put(statementKey, statement);
11699  }
11700  return statement;
11701  }
11702 
11703  PreparedStatement prepareStatement(String sqlStatement, int generateKeys) throws SQLException {
11704  PrepareStatement prepareStatement = new PrepareStatement(this.getConnection(), sqlStatement);
11705  executeCommand(prepareStatement);
11706  return prepareStatement.getPreparedStatement();
11707  }
11708 
11709  Statement createStatement() throws SQLException {
11710  CreateStatement createStatement = new CreateStatement(this.connection);
11711  executeCommand(createStatement);
11712  return createStatement.getStatement();
11713  }
11714 
11715  void beginTransaction() throws SQLException {
11716  SetAutoCommit setAutoCommit = new SetAutoCommit(connection, false);
11717  executeCommand(setAutoCommit);
11718  }
11719 
11720  void commitTransaction() throws SQLException {
11721  Commit commit = new Commit(connection);
11722  executeCommand(commit);
11723  // You must turn auto commit back on when done with the transaction.
11724  SetAutoCommit setAutoCommit = new SetAutoCommit(connection, true);
11725  executeCommand(setAutoCommit);
11726  }
11727 
11733  void rollbackTransaction() {
11734  try {
11735  connection.rollback();
11736  } catch (SQLException e) {
11737  logger.log(Level.SEVERE, "Error rolling back transaction", e);
11738  }
11739  try {
11740  connection.setAutoCommit(true);
11741  } catch (SQLException e) {
11742  logger.log(Level.SEVERE, "Error restoring auto-commit", e);
11743  }
11744  }
11745 
11753  void rollbackTransactionWithThrow() throws SQLException {
11754  try {
11755  connection.rollback();
11756  } finally {
11757  connection.setAutoCommit(true);
11758  }
11759  }
11760 
11761  ResultSet executeQuery(Statement statement, String query) throws SQLException {
11762  ExecuteQuery queryCommand = new ExecuteQuery(statement, query);
11763  executeCommand(queryCommand);
11764  return queryCommand.getResultSet();
11765  }
11766 
11776  ResultSet executeQuery(PreparedStatement statement) throws SQLException {
11777  ExecutePreparedStatementQuery executePreparedStatementQuery = new ExecutePreparedStatementQuery(statement);
11778  executeCommand(executePreparedStatementQuery);
11779  return executePreparedStatementQuery.getResultSet();
11780  }
11781 
11782  void executeUpdate(Statement statement, String update) throws SQLException {
11783  executeUpdate(statement, update, Statement.NO_GENERATED_KEYS);
11784  }
11785 
11786  void executeUpdate(Statement statement, String update, int generateKeys) throws SQLException {
11787  ExecuteStatementUpdate executeStatementUpdate = new ExecuteStatementUpdate(statement, update);
11788  executeCommand(executeStatementUpdate);
11789  }
11790 
11791  void executeUpdate(PreparedStatement statement) throws SQLException {
11792  ExecutePreparedStatementUpdate executePreparedStatementUpdate = new ExecutePreparedStatementUpdate(statement);
11793  executeCommand(executePreparedStatementUpdate);
11794  }
11795 
11799  @Override
11800  public void close() {
11801  try {
11802  for (PreparedStatement stmt:preparedStatements.values()) {
11803  closeStatement(stmt);
11804  }
11805  for (PreparedStatement stmt:adHocPreparedStatements.values()) {
11806  closeStatement(stmt);
11807  }
11808  connection.close();
11809  } catch (SQLException ex) {
11810  logger.log(Level.SEVERE, "Unable to close connection to case database", ex);
11811  }
11812  }
11813 
11814  Connection getConnection() {
11815  return this.connection;
11816  }
11817  }
11818 
11822  private final class SQLiteConnection extends CaseDbConnection {
11823 
11824  private static final int DATABASE_LOCKED_ERROR = 0; // This should be 6 according to documentation, but it has been observed to be 0.
11825  private static final int SQLITE_BUSY_ERROR = 5;
11826 
11827  SQLiteConnection(Connection conn) {
11828  super(conn);
11829  }
11830 
11831  @Override
11832  void executeCommand(DbCommand command) throws SQLException {
11833  int retryCounter = 0;
11834  while (true) {
11835  try {
11836  command.execute(); // Perform the operation
11837  break;
11838  } catch (SQLException ex) {
11839  if ((ex.getErrorCode() == SQLITE_BUSY_ERROR || ex.getErrorCode() == DATABASE_LOCKED_ERROR) && retryCounter < MAX_RETRIES) {
11840  try {
11841 
11842  // We do not notify of error here, as this is not an
11843  // error condition. It is likely a temporary busy or
11844  // locked issue and we will retry.
11845  retryCounter++;
11846  Thread.sleep(SLEEP_LENGTH_IN_MILLISECONDS);
11847  } catch (InterruptedException exp) {
11848  Logger.getLogger(SleuthkitCase.class.getName()).log(Level.WARNING, "Unexpectedly unable to wait for database.", exp);
11849  }
11850  } else {
11851  throw ex;
11852  }
11853  }
11854  }
11855  }
11856  }
11857 
11861  private final class PostgreSQLConnection extends CaseDbConnection {
11862 
11863  private final String COMMUNICATION_ERROR = PSQLState.COMMUNICATION_ERROR.getState();
11864  private final String SYSTEM_ERROR = PSQLState.SYSTEM_ERROR.getState();
11865  private final String UNKNOWN_STATE = PSQLState.UNKNOWN_STATE.getState();
11866  private static final int MAX_RETRIES = 3;
11867 
11868  PostgreSQLConnection(Connection conn) {
11869  super(conn);
11870  }
11871 
11872  @Override
11873  void executeUpdate(Statement statement, String update, int generateKeys) throws SQLException {
11874  CaseDbConnection.ExecuteStatementUpdateGenerateKeys executeStatementUpdateGenerateKeys = new CaseDbConnection.ExecuteStatementUpdateGenerateKeys(statement, update, generateKeys);
11875  executeCommand(executeStatementUpdateGenerateKeys);
11876  }
11877 
11878  @Override
11879  PreparedStatement prepareStatement(String sqlStatement, int generateKeys) throws SQLException {
11880  CaseDbConnection.PrepareStatementGenerateKeys prepareStatementGenerateKeys = new CaseDbConnection.PrepareStatementGenerateKeys(this.getConnection(), sqlStatement, generateKeys);
11881  executeCommand(prepareStatementGenerateKeys);
11882  return prepareStatementGenerateKeys.getPreparedStatement();
11883  }
11884 
11885  @Override
11886  void executeCommand(DbCommand command) throws SQLException {
11887  SQLException lastException = null;
11888  for (int retries = 0; retries < MAX_RETRIES; retries++) {
11889  try {
11890  command.execute();
11891  lastException = null; // reset since we had a successful execution
11892  break;
11893  } catch (SQLException ex) {
11894  lastException = ex;
11895  String sqlState = ex.getSQLState();
11896  if (sqlState == null || sqlState.equals(COMMUNICATION_ERROR) || sqlState.equals(SYSTEM_ERROR) || sqlState.equals(UNKNOWN_STATE)) {
11897  try {
11898  Thread.sleep(SLEEP_LENGTH_IN_MILLISECONDS);
11899  } catch (InterruptedException exp) {
11900  Logger.getLogger(SleuthkitCase.class.getName()).log(Level.WARNING, "Unexpectedly unable to wait for database.", exp);
11901  }
11902  } else {
11903  throw ex;
11904  }
11905  }
11906  }
11907 
11908  // rethrow the exception if we bailed because of too many retries
11909  if (lastException != null) {
11910  throw lastException;
11911  }
11912  }
11913  }
11914 
11929  public static final class CaseDbTransaction {
11930 
11931  private final CaseDbConnection connection;
11932  private SleuthkitCase sleuthkitCase;
11933 
11934  private CaseDbTransaction(SleuthkitCase sleuthkitCase, CaseDbConnection connection) throws TskCoreException {
11935  this.connection = connection;
11936  this.sleuthkitCase = sleuthkitCase;
11937  try {
11938  this.connection.beginTransaction();
11939  } catch (SQLException ex) {
11940  throw new TskCoreException("Failed to create transaction on case database", ex);
11941  }
11942  sleuthkitCase.acquireSingleUserCaseWriteLock();
11943  }
11944 
11952  CaseDbConnection getConnection() {
11953  return this.connection;
11954  }
11955 
11962  public void commit() throws TskCoreException {
11963  try {
11964  this.connection.commitTransaction();
11965  } catch (SQLException ex) {
11966  throw new TskCoreException("Failed to commit transaction on case database", ex);
11967  } finally {
11968  close();
11969  }
11970  }
11971 
11978  public void rollback() throws TskCoreException {
11979  try {
11980  this.connection.rollbackTransactionWithThrow();
11981  } catch (SQLException ex) {
11982  throw new TskCoreException("Case database transaction rollback failed", ex);
11983  } finally {
11984  close();
11985  }
11986  }
11987 
11992  void close() {
11993  this.connection.close();
11994  sleuthkitCase.releaseSingleUserCaseWriteLock();
11995  }
11996  }
11997 
12007  public final class CaseDbQuery implements AutoCloseable {
12008 
12009  private ResultSet resultSet;
12010  private CaseDbConnection connection;
12011 
12012  private CaseDbQuery(String query) throws TskCoreException {
12013  this(query, false);
12014  }
12015 
12016  private CaseDbQuery(String query, boolean allowWriteQuery) throws TskCoreException {
12017  if (!allowWriteQuery) {
12018  if (!query.regionMatches(true, 0, "SELECT", 0, "SELECT".length())) {
12019  throw new TskCoreException("Unsupported query: Only SELECT queries are supported.");
12020  }
12021  }
12022  try {
12023  connection = connections.getConnection();
12024  } catch (TskCoreException ex) {
12025  throw new TskCoreException("Error getting connection for query: ", ex);
12026  }
12027 
12028  try {
12030  resultSet = connection.executeQuery(connection.createStatement(), query);
12031  } catch (SQLException ex) {
12033  throw new TskCoreException("Error executing query: ", ex);
12034  }
12035  }
12036 
12042  public ResultSet getResultSet() {
12043  return resultSet;
12044  }
12045 
12046  @Override
12047  public void close() throws TskCoreException {
12048  try {
12049  if (resultSet != null) {
12050  final Statement statement = resultSet.getStatement();
12051  if (statement != null) {
12052  statement.close();
12053  }
12054  resultSet.close();
12055  }
12056  connection.close();
12057  } catch (SQLException ex) {
12058  throw new TskCoreException("Error closing query: ", ex);
12059  } finally {
12061  }
12062  }
12063  }
12064 
12072  @Deprecated
12073  public void addErrorObserver(ErrorObserver observer) {
12074  sleuthkitCaseErrorObservers.add(observer);
12075  }
12076 
12084  @Deprecated
12085  public void removeErrorObserver(ErrorObserver observer) {
12086  int i = sleuthkitCaseErrorObservers.indexOf(observer);
12087  if (i >= 0) {
12088  sleuthkitCaseErrorObservers.remove(i);
12089  }
12090  }
12091 
12100  @Deprecated
12101  public void submitError(String context, String errorMessage) {
12102  for (ErrorObserver observer : sleuthkitCaseErrorObservers) {
12103  if (observer != null) {
12104  try {
12105  observer.receiveError(context, errorMessage);
12106  } catch (Exception ex) {
12107  logger.log(Level.SEVERE, "Observer client unable to receive message: {0}, {1}", new Object[]{context, errorMessage, ex});
12108 
12109  }
12110  }
12111  }
12112  }
12113 
12119  @Deprecated
12120  public interface ErrorObserver {
12121 
12128  public enum Context {
12129 
12133  IMAGE_READ_ERROR("Image File Read Error"),
12137  DATABASE_READ_ERROR("Database Read Error");
12138 
12139  private final String contextString;
12140 
12141  private Context(String context) {
12142  this.contextString = context;
12143  }
12144 
12145  public String getContextString() {
12146  return contextString;
12147  }
12148  };
12149 
12150  void receiveError(String context, String errorMessage);
12151  }
12152 
12163  @Deprecated
12164  long getDataSourceObjectId(long objectId) {
12165  try {
12166  CaseDbConnection connection = connections.getConnection();
12167  try {
12168  return getDataSourceObjectId(connection, objectId);
12169  } finally {
12170  connection.close();
12171  }
12172  } catch (TskCoreException ex) {
12173  logger.log(Level.SEVERE, "Error getting data source object id for a file", ex);
12174  return 0;
12175  }
12176  }
12177 
12187  @Deprecated
12188  public long getLastObjectId() throws TskCoreException {
12189  CaseDbConnection connection = connections.getConnection();
12191  ResultSet rs = null;
12192  try {
12193  // SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects
12194  PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_MAX_OBJECT_ID);
12195  rs = connection.executeQuery(statement);
12196  long id = -1;
12197  if (rs.next()) {
12198  id = rs.getLong("max_obj_id");
12199  }
12200  return id;
12201  } catch (SQLException e) {
12202  throw new TskCoreException("Error getting last object id", e);
12203  } finally {
12204  closeResultSet(rs);
12205  connection.close();
12207  }
12208  }
12209 
12223  @Deprecated
12224  public List<FsContent> findFilesWhere(String sqlWhereClause) throws TskCoreException {
12225  CaseDbConnection connection = connections.getConnection();
12227  Statement s = null;
12228  ResultSet rs = null;
12229  try {
12230  s = connection.createStatement();
12231  rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
12232  List<FsContent> results = new ArrayList<FsContent>();
12233  List<AbstractFile> temp = resultSetToAbstractFiles(rs, connection);
12234  for (AbstractFile f : temp) {
12235  final TSK_DB_FILES_TYPE_ENUM type = f.getType();
12236  if (type.equals(TskData.TSK_DB_FILES_TYPE_ENUM.FS)) {
12237  results.add((FsContent) f);
12238  }
12239  }
12240  return results;
12241  } catch (SQLException e) {
12242  throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findFilesWhere().", e);
12243  } finally {
12244  closeResultSet(rs);
12245  closeStatement(s);
12246  connection.close();
12248  }
12249  }
12250 
12262  @Deprecated
12263  public int getArtifactTypeID(String artifactTypeName) throws TskCoreException {
12264  CaseDbConnection connection = connections.getConnection();
12266  Statement s = null;
12267  ResultSet rs = null;
12268  try {
12269  s = connection.createStatement();
12270  rs = connection.executeQuery(s, "SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = '" + artifactTypeName + "'"); //NON-NLS
12271  int typeId = -1;
12272  if (rs.next()) {
12273  typeId = rs.getInt("artifact_type_id");
12274  }
12275  return typeId;
12276  } catch (SQLException ex) {
12277  throw new TskCoreException("Error getting artifact type id", ex);
12278  } finally {
12279  closeResultSet(rs);
12280  closeStatement(s);
12281  connection.close();
12283  }
12284  }
12285 
12295  @Deprecated
12296  public ArrayList<BlackboardArtifact.ARTIFACT_TYPE> getBlackboardArtifactTypes() throws TskCoreException {
12297  return new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>(Arrays.asList(BlackboardArtifact.ARTIFACT_TYPE.values()));
12298  }
12299 
12313  @Deprecated
12314  public int addArtifactType(String artifactTypeName, String displayName) throws TskCoreException {
12315  try {
12316  return addBlackboardArtifactType(artifactTypeName, displayName).getTypeID();
12317  } catch (TskDataException ex) {
12318  throw new TskCoreException("Failed to add artifact type.", ex);
12319  }
12320  }
12321 
12335  @Deprecated
12336  public int addAttrType(String attrTypeString, String displayName) throws TskCoreException {
12337  try {
12338  return addArtifactAttributeType(attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, displayName).getTypeID();
12339  } catch (TskDataException ex) {
12340  throw new TskCoreException("Couldn't add new attribute type");
12341  }
12342  }
12343 
12354  @Deprecated
12355  public int getAttrTypeID(String attrTypeName) throws TskCoreException {
12356  CaseDbConnection connection = connections.getConnection();
12358  Statement s = null;
12359  ResultSet rs = null;
12360  try {
12361  s = connection.createStatement();
12362  rs = connection.executeQuery(s, "SELECT attribute_type_id FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName + "'"); //NON-NLS
12363  int typeId = -1;
12364  if (rs.next()) {
12365  typeId = rs.getInt("attribute_type_id");
12366  }
12367  return typeId;
12368  } catch (SQLException ex) {
12369  throw new TskCoreException("Error getting attribute type id", ex);
12370  } finally {
12371  closeResultSet(rs);
12372  closeStatement(s);
12373  connection.close();
12375  }
12376  }
12377 
12390  @Deprecated
12391  public String getAttrTypeString(int attrTypeID) throws TskCoreException {
12392  CaseDbConnection connection = connections.getConnection();
12394  Statement s = null;
12395  ResultSet rs = null;
12396  try {
12397  s = connection.createStatement();
12398  rs = connection.executeQuery(s, "SELECT type_name FROM blackboard_attribute_types WHERE attribute_type_id = " + attrTypeID); //NON-NLS
12399  if (rs.next()) {
12400  return rs.getString("type_name");
12401  } else {
12402  throw new TskCoreException("No type with that id");
12403  }
12404  } catch (SQLException ex) {
12405  throw new TskCoreException("Error getting or creating a attribute type name", ex);
12406  } finally {
12407  closeResultSet(rs);
12408  closeStatement(s);
12409  connection.close();
12411  }
12412  }
12413 
12426  @Deprecated
12427  public String getAttrTypeDisplayName(int attrTypeID) throws TskCoreException {
12428  CaseDbConnection connection = connections.getConnection();
12430  Statement s = null;
12431  ResultSet rs = null;
12432  try {
12433  s = connection.createStatement();
12434  rs = connection.executeQuery(s, "SELECT display_name FROM blackboard_attribute_types WHERE attribute_type_id = " + attrTypeID); //NON-NLS
12435  if (rs.next()) {
12436  return rs.getString("display_name");
12437  } else {
12438  throw new TskCoreException("No type with that id");
12439  }
12440  } catch (SQLException ex) {
12441  throw new TskCoreException("Error getting or creating a attribute type name", ex);
12442  } finally {
12443  closeResultSet(rs);
12444  closeStatement(s);
12445  connection.close();
12447  }
12448  }
12449 
12459  @Deprecated
12460  public ArrayList<BlackboardAttribute.ATTRIBUTE_TYPE> getBlackboardAttributeTypes() throws TskCoreException {
12461  return new ArrayList<BlackboardAttribute.ATTRIBUTE_TYPE>(Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.values()));
12462  }
12463 
12479  @Deprecated
12480  public ResultSet runQuery(String query) throws SQLException {
12481  CaseDbConnection connection;
12482  try {
12483  connection = connections.getConnection();
12484  } catch (TskCoreException ex) {
12485  throw new SQLException("Error getting connection for ad hoc query", ex);
12486  }
12488  try {
12489  return connection.executeQuery(connection.createStatement(), query);
12490  } finally {
12491  //TODO unlock should be done in closeRunQuery()
12492  //but currently not all code calls closeRunQuery - need to fix this
12493  connection.close();
12495  }
12496  }
12497 
12507  @Deprecated
12508  public void closeRunQuery(ResultSet resultSet) throws SQLException {
12509  final Statement statement = resultSet.getStatement();
12510  resultSet.close();
12511  if (statement != null) {
12512  statement.close();
12513  }
12514  }
12515 
12532  @Deprecated
12533  public LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, long containerId, List<TskFileRange> data) throws TskCoreException {
12534  CarvingResult.CarvedFile carvedFile = new CarvingResult.CarvedFile(carvedFileName, carvedFileSize, data);
12535  List<CarvingResult.CarvedFile> files = new ArrayList<CarvingResult.CarvedFile>();
12536  files.add(carvedFile);
12537  CarvingResult carvingResult;
12538  Content parent = getContentById(containerId);
12539  if (parent instanceof FileSystem
12540  || parent instanceof Volume
12541  || parent instanceof Image) {
12542  carvingResult = new CarvingResult(parent, files);
12543  } else {
12544  throw new TskCoreException(String.format("Parent (id =%d) is not an file system, volume or image", containerId));
12545  }
12546  return addCarvedFiles(carvingResult).get(0);
12547  }
12548 
12562  @Deprecated
12563  public List<LayoutFile> addCarvedFiles(List<CarvedFileContainer> filesToAdd) throws TskCoreException {
12564  List<CarvingResult.CarvedFile> carvedFiles = new ArrayList<CarvingResult.CarvedFile>();
12565  for (CarvedFileContainer container : filesToAdd) {
12566  CarvingResult.CarvedFile carvedFile = new CarvingResult.CarvedFile(container.getName(), container.getSize(), container.getRanges());
12567  carvedFiles.add(carvedFile);
12568  }
12569  CarvingResult carvingResult;
12570  Content parent = getContentById(filesToAdd.get(0).getId());
12571  if (parent instanceof FileSystem
12572  || parent instanceof Volume
12573  || parent instanceof Image) {
12574  carvingResult = new CarvingResult(parent, carvedFiles);
12575  } else {
12576  throw new TskCoreException(String.format("Parent (id =%d) is not an file system, volume or image", parent.getId()));
12577  }
12578  return addCarvedFiles(carvingResult);
12579  }
12580 
12610  @Deprecated
12611  public DerivedFile addDerivedFile(String fileName, String localPath,
12612  long size, long ctime, long crtime, long atime, long mtime,
12613  boolean isFile, AbstractFile parentFile,
12614  String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException {
12615  return addDerivedFile(fileName, localPath, size, ctime, crtime, atime, mtime,
12616  isFile, parentFile, rederiveDetails, toolName, toolVersion,
12617  otherDetails, TskData.EncodingType.NONE);
12618  }
12619 
12649  @Deprecated
12650  public LocalFile addLocalFile(String fileName, String localPath,
12651  long size, long ctime, long crtime, long atime, long mtime,
12652  String md5, FileKnown known, String mimeType,
12653  boolean isFile, TskData.EncodingType encodingType,
12654  Content parent, CaseDbTransaction transaction) throws TskCoreException {
12655 
12656  return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime,
12657  md5, null, known, mimeType, isFile, encodingType,
12658  parent, transaction);
12659  }
12660 
12685  @Deprecated
12686  public LocalFile addLocalFile(String fileName, String localPath,
12687  long size, long ctime, long crtime, long atime, long mtime,
12688  boolean isFile,
12689  AbstractFile parent, CaseDbTransaction transaction) throws TskCoreException {
12690  return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile,
12691  TskData.EncodingType.NONE, parent, transaction);
12692  }
12693 
12713  @Deprecated
12714  public LocalFile addLocalFile(String fileName, String localPath,
12715  long size, long ctime, long crtime, long atime, long mtime,
12716  boolean isFile,
12717  AbstractFile parent) throws TskCoreException {
12718  return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime,
12719  isFile, TskData.EncodingType.NONE, parent);
12720  }
12721 
12738  @Deprecated
12739  public AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans) {
12740  return this.caseHandle.initAddImageProcess(timezone, addUnallocSpace, noFatFsOrphans, "", this);
12741  }
12742 
12753  @Deprecated
12754  public Collection<FileSystem> getFileSystems(Image image) {
12755  try {
12756  return getImageFileSystems(image);
12757  } catch (TskCoreException ex) {
12758  logger.log(Level.SEVERE, "Error loading all file systems for image with ID {0}", image.getId());
12759  return new ArrayList<>();
12760  }
12761  }
12762 
12770  @Deprecated
12771  public void acquireExclusiveLock() {
12773  }
12774 
12782  @Deprecated
12783  public void releaseExclusiveLock() {
12785  }
12786 
12794  @Deprecated
12795  public void acquireSharedLock() {
12797  }
12798 
12806  @Deprecated
12807  public void releaseSharedLock() {
12809  }
12810 };
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
List< AbstractFile > findAllFilesInFolderWhere(long parentId, String sqlWhereClause)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, String md5, String sha256, FileKnown known, String mimeType, boolean isFile, TskData.EncodingType encodingType, Content parent, CaseDbTransaction transaction)
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.