19 package org.sleuthkit.datamodel;
 
   22 import java.io.UnsupportedEncodingException;
 
   23 import java.net.URLEncoder;
 
   24 import java.sql.Connection;
 
   25 import java.sql.DriverManager;
 
   26 import java.sql.SQLException;
 
   27 import java.sql.Statement;
 
   28 import java.util.Properties;
 
   29 import java.util.logging.Logger;
 
   30 import java.util.logging.Level;
 
   37 class CaseDatabaseFactory {
 
   39         private static final Logger logger = Logger.getLogger(CaseDatabaseFactory.class.getName());
 
   40         private final SQLHelper dbQueryHelper;
 
   41         private final DbCreationHelper dbCreationHelper;
 
   47         final static String SSL_NONVERIFY_URL = 
"?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require";
 
   52         final static String SSL_VERIFY_DEFAULT_URL = 
"?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca";
 
   70         static String getCustomPostrgesSslVerificationUrl(String customSslValidationClassName) {
 
   71                 return "?ssl=true&sslfactory=" + customSslValidationClassName + 
"&sslmode=verify-ca";
 
   79         CaseDatabaseFactory(String dbPath) {            
 
   80                 this.dbQueryHelper = 
new SQLiteHelper();
 
   81                 this.dbCreationHelper = 
new SQLiteDbCreationHelper(dbPath);
 
   94         CaseDatabaseFactory(String caseName, CaseDbConnectionInfo info) {
 
   95                 this.dbQueryHelper = 
new PostgreSQLHelper();
 
   96                 this.dbCreationHelper = 
new PostgreSQLDbCreationHelper(caseName, info);
 
  105         void createCaseDatabase() throws TskCoreException {
 
  115         private void createDatabase() throws TskCoreException {
 
  116                 dbCreationHelper.createDatabase();
 
  124         private void initializeSchema() throws TskCoreException {
 
  125                 try (Connection conn = dbCreationHelper.getConnection()) {
 
  127                         dbCreationHelper.performPreInitialization(conn);
 
  134                         dbCreationHelper.performPostTableInitialization(conn);
 
  138                 } 
catch (SQLException ex) {
 
  139                         throw new TskCoreException(
"Error initializing case database", ex);
 
  150         private void addDbInfo(Connection conn) 
throws TskCoreException {
 
  151                 CaseDbSchemaVersionNumber version = SleuthkitCase.CURRENT_DB_SCHEMA_VERSION;
 
  152                 long tskVersionNum = SleuthkitJNI.getSleuthkitVersion(); 
 
  154                 try (Statement stmt = conn.createStatement()) {
 
  155                         stmt.execute(
"CREATE TABLE tsk_db_info (schema_ver INTEGER, tsk_ver INTEGER, schema_minor_ver INTEGER)");
 
  156                         stmt.execute(
"INSERT INTO tsk_db_info (schema_ver, tsk_ver, schema_minor_ver) VALUES (" + 
 
  157                                         version.getMajor() + 
", " + tskVersionNum + 
", " + version.getMinor() + 
");");
 
  159                         stmt.execute(
"CREATE TABLE tsk_db_info_extended (name TEXT PRIMARY KEY, value TEXT NOT NULL);");
 
  160                         stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('TSK_VERSION', '" + tskVersionNum + 
"');");
 
  161                         stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('SCHEMA_MAJOR_VERSION', '" + version.getMajor() + 
"');");
 
  162                         stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('SCHEMA_MINOR_VERSION', '" + version.getMinor() + 
"');");
 
  163                         stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATION_SCHEMA_MAJOR_VERSION', '" + version.getMajor() + 
"');");
 
  164                         stmt.execute(
"INSERT INTO tsk_db_info_extended (name, value) VALUES ('CREATION_SCHEMA_MINOR_VERSION', '" + version.getMinor() + 
"');");
 
  165                 } 
catch (SQLException ex) {
 
  166                         throw new TskCoreException(
"Error initializing db_info tables", ex);
 
  177         private void addTables(Connection conn) 
throws TskCoreException {
 
  178                 try (Statement stmt = conn.createStatement()) {
 
  179                         createTskObjects(stmt);
 
  180                         createHostTables(stmt);
 
  181                         createAccountTables(stmt);
 
  182                         createFileTables(stmt);
 
  183                         createArtifactTables(stmt);
 
  184                         createAnalysisResultsTables(stmt);
 
  185                         createTagTables(stmt);
 
  186                         createIngestTables(stmt);
 
  187                         createEventTables(stmt);
 
  188                         createAttributeTables(stmt);
 
  189                         createAccountInstancesAndArtifacts(stmt);
 
  190                 } 
catch (SQLException ex) {
 
  191                         throw new TskCoreException(
"Error initializing tables", ex);
 
  196         private void createTskObjects(Statement stmt) 
throws SQLException {
 
  198                 stmt.execute(
"CREATE TABLE tsk_objects (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, par_obj_id " + dbQueryHelper.getBigIntType() 
 
  199                                 + 
", type INTEGER NOT NULL, UNIQUE (obj_id), FOREIGN KEY (par_obj_id) REFERENCES tsk_objects (obj_id) ON DELETE CASCADE)");
 
  202         private void createFileTables(Statement stmt) 
throws SQLException {
 
  204                 stmt.execute(
"CREATE TABLE tsk_image_info (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, type INTEGER, ssize INTEGER, "  
  205                                 + 
"tzone TEXT, size " + dbQueryHelper.getBigIntType() + 
", md5 TEXT, sha1 TEXT, sha256 TEXT, display_name TEXT, " 
  206                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  208                 stmt.execute(
"CREATE TABLE tsk_image_names (obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, name TEXT NOT NULL, " 
  209                                 + 
"sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  211                 stmt.execute(
"CREATE TABLE tsk_vs_info (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, vs_type INTEGER NOT NULL, " 
  212                                 + 
"img_offset " + dbQueryHelper.getBigIntType() + 
" NOT NULL, block_size " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  213                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  215                 stmt.execute(
"CREATE TABLE tsk_vs_parts (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  216                                 + 
"addr " + dbQueryHelper.getBigIntType() + 
" NOT NULL, start " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  217                                 + 
"length " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  218                                 + dbQueryHelper.getVSDescColName() + 
" TEXT, " 
  219                                 + 
"flags INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");            
 
  221                 stmt.execute(
"CREATE TABLE tsk_pool_info (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  222                                 + 
"pool_type INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");
 
  224                 stmt.execute(
"CREATE TABLE data_source_info (obj_id " + dbQueryHelper.getBigIntType() + 
" PRIMARY KEY, device_id TEXT NOT NULL, " 
  225                                 + 
"time_zone TEXT NOT NULL, acquisition_details TEXT, added_date_time "+ dbQueryHelper.getBigIntType() + 
", " 
  226                                 + 
"acquisition_tool_settings TEXT, acquisition_tool_name TEXT, acquisition_tool_version TEXT, " 
  227                                 + 
"host_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  228                                 + 
"FOREIGN KEY(host_id) REFERENCES tsk_hosts(id), " 
  229                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  231                 stmt.execute(
"CREATE TABLE tsk_fs_info (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  232                                 + 
"data_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  233                                 + 
"img_offset " + dbQueryHelper.getBigIntType() + 
" NOT NULL, fs_type INTEGER NOT NULL, " 
  234                                 + 
"block_size " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  235                                 + 
"block_count " + dbQueryHelper.getBigIntType() + 
" NOT NULL, root_inum " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  236                                 + 
"first_inum " + dbQueryHelper.getBigIntType() + 
" NOT NULL, last_inum " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  237                                 + 
"display_name TEXT, "  
  238                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, " 
  239                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  241                 stmt.execute(
"CREATE TABLE file_collection_status_types (collection_status_type INTEGER PRIMARY KEY, name TEXT NOT NULL)");
 
  243                 stmt.execute(
"CREATE TABLE tsk_files (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  244                                 + 
"fs_obj_id " + dbQueryHelper.getBigIntType() + 
", data_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  245                                 + 
"attr_type INTEGER, attr_id INTEGER, "  
  246                                 + 
"name TEXT NOT NULL, meta_addr " + dbQueryHelper.getBigIntType() + 
", meta_seq " + dbQueryHelper.getBigIntType() + 
", " 
  247                                 + 
"type INTEGER, has_layout INTEGER, has_path INTEGER, " 
  248                                 + 
"dir_type INTEGER, meta_type INTEGER, dir_flags INTEGER, meta_flags INTEGER, size " + dbQueryHelper.getBigIntType() + 
", " 
  249                                 + 
"ctime " + dbQueryHelper.getBigIntType() + 
", " 
  250                                 + 
"crtime " + dbQueryHelper.getBigIntType() + 
", atime " + dbQueryHelper.getBigIntType() + 
", " 
  251                                 + 
"mtime " + dbQueryHelper.getBigIntType() + 
", mode INTEGER, uid INTEGER, gid INTEGER, md5 TEXT, sha256 TEXT, sha1 TEXT," 
  253                                 + 
"parent_path TEXT, mime_type TEXT, extension TEXT, " 
  254                                 + 
"owner_uid TEXT DEFAULT NULL, " 
  255                                 + 
"os_account_obj_id " + dbQueryHelper.getBigIntType() + 
" DEFAULT NULL, " 
  256                                 + 
"collected INTEGER NOT NULL, " 
  257                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  258                                 + 
"FOREIGN KEY(fs_obj_id) REFERENCES tsk_fs_info(obj_id) ON DELETE CASCADE, " 
  259                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, " 
  260                                 + 
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE SET NULL, " 
  261                                 + 
"FOREIGN KEY(collected) REFERENCES file_collection_status_types (collection_status_type))" ); 
 
  263                 stmt.execute(
"CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL)");
 
  265                 stmt.execute(
"CREATE TABLE tsk_files_path (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, path TEXT NOT NULL, " 
  266                                 + 
"encoding_type INTEGER NOT NULL, FOREIGN KEY(encoding_type) references file_encoding_types(encoding_type), " 
  267                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  269                 stmt.execute(
"CREATE TABLE tsk_files_derived (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  270                                 + 
"derived_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, rederive TEXT, " 
  271                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  273                 stmt.execute(
"CREATE TABLE tsk_files_derived_method (derived_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  274                                 + 
"tool_name TEXT NOT NULL, tool_version TEXT NOT NULL, other TEXT)");          
 
  276                 stmt.execute(
"CREATE TABLE tsk_file_layout (obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  277                                 + 
"byte_start " + dbQueryHelper.getBigIntType() + 
" NOT NULL, byte_len " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  278                                 + 
"sequence INTEGER NOT NULL, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");
 
  280                 stmt.execute(
"CREATE TABLE reports (obj_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, path TEXT NOT NULL, " 
  281                                 + 
"crtime INTEGER NOT NULL, src_module_name TEXT NOT NULL, report_name TEXT NOT NULL, " 
  282                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE);");            
 
  285         private void createArtifactTables(Statement stmt) 
throws SQLException {
 
  286                 stmt.execute(
"CREATE TABLE blackboard_artifact_types (artifact_type_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  287                                 + 
"type_name TEXT NOT NULL, display_name TEXT," 
  288                                 + 
"category_type INTEGER DEFAULT 0)");
 
  290                 stmt.execute(
"CREATE TABLE blackboard_attribute_types (attribute_type_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  291                                 + 
"type_name TEXT NOT NULL, display_name TEXT, value_type INTEGER NOT NULL)");
 
  293                 stmt.execute(
"CREATE TABLE review_statuses (review_status_id INTEGER PRIMARY KEY, " 
  294                                 + 
"review_status_name TEXT NOT NULL, " 
  295                                 + 
"display_name TEXT NOT NULL)");
 
  297                 stmt.execute(
"CREATE TABLE blackboard_artifacts (artifact_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  298                                 + 
"obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  299                                 + 
"artifact_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  300                                 + 
"data_source_obj_id " + dbQueryHelper.getBigIntType() + 
", " 
  301                                 + 
"artifact_type_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  302                                 + 
"review_status_id INTEGER NOT NULL, " 
  303                                 + 
"UNIQUE (artifact_obj_id)," 
  304                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  305                                 + 
"FOREIGN KEY(artifact_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  306                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  307                                 + 
"FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), " 
  308                                 + 
"FOREIGN KEY(review_status_id) REFERENCES review_statuses(review_status_id))");
 
  314                 stmt.execute(
"CREATE TABLE blackboard_attributes (artifact_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  315                                 + 
"artifact_type_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  316                                 + 
"source TEXT, context TEXT, attribute_type_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  317                                 + 
"value_type INTEGER NOT NULL, value_byte " + dbQueryHelper.getBlobType() + 
", " 
  318                                 + 
"value_text TEXT, value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + 
", value_double NUMERIC(20, 10), " 
  319                                 + 
"FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, " 
  320                                 + 
"FOREIGN KEY(artifact_type_id) REFERENCES blackboard_artifact_types(artifact_type_id), " 
  321                                 + 
"FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");  
 
  324         private void createAnalysisResultsTables(Statement stmt) 
throws SQLException  {
 
  325                 stmt.execute(
"CREATE TABLE tsk_analysis_results (artifact_obj_id " + dbQueryHelper.getBigIntType() + 
" PRIMARY KEY, " 
  326                                 + 
"conclusion TEXT, " 
  327                                 + 
"significance INTEGER NOT NULL, " 
  328                                 + 
"priority INTEGER NOT NULL, " 
  329                                 + 
"configuration TEXT, justification TEXT, " 
  330                                 + 
"ignore_score INTEGER DEFAULT 0, "  
  331                                 + 
"FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE" 
  334                 stmt.execute(
"CREATE TABLE tsk_aggregate_score( obj_id " + dbQueryHelper.getBigIntType() + 
" PRIMARY KEY, " 
  335                                 + 
"data_source_obj_id " + dbQueryHelper.getBigIntType() + 
", " 
  336                                 + 
"significance INTEGER NOT NULL, " 
  337                                 + 
"priority INTEGER NOT NULL, " 
  339                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  340                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE " 
  344         private void createTagTables(Statement stmt) 
throws SQLException {
 
  345                 stmt.execute(
"CREATE TABLE tsk_tag_sets (tag_set_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, name TEXT UNIQUE)");
 
  346                 stmt.execute(
"CREATE TABLE tag_names (tag_name_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, display_name TEXT UNIQUE, " 
  347                                 + 
"description TEXT NOT NULL, color TEXT NOT NULL, knownStatus INTEGER NOT NULL," 
  348                                 + 
" tag_set_id " + dbQueryHelper.getBigIntType() + 
", rank INTEGER, FOREIGN KEY(tag_set_id) REFERENCES tsk_tag_sets(tag_set_id) ON DELETE SET NULL)");
 
  350                 stmt.execute(
"CREATE TABLE tsk_examiners (examiner_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  351                                 + 
"login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))");
 
  353                 stmt.execute(
"CREATE TABLE content_tags (tag_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  354                                 + 
"obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, tag_name_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  355                                 + 
"comment TEXT NOT NULL, begin_byte_offset " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  356                                 + 
"end_byte_offset " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  357                                 + 
"examiner_id " + dbQueryHelper.getBigIntType() + 
", " 
  358                                 + 
"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id) ON DELETE CASCADE, " 
  359                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  360                                 + 
"FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id) ON DELETE CASCADE)");
 
  362                 stmt.execute(
"CREATE TABLE blackboard_artifact_tags (tag_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  363                                 + 
"artifact_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, tag_name_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  364                                 + 
"comment TEXT NOT NULL,  examiner_id " + dbQueryHelper.getBigIntType() + 
", " 
  365                                 + 
"FOREIGN KEY(examiner_id) REFERENCES tsk_examiners(examiner_id) ON DELETE CASCADE, " 
  366                                 + 
"FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE, " 
  367                                 + 
"FOREIGN KEY(tag_name_id) REFERENCES tag_names(tag_name_id) ON DELETE CASCADE)");
 
  376         private void addIndexes(Connection conn) 
throws TskCoreException {
 
  377                 try (Statement stmt = conn.createStatement()) {
 
  379                         stmt.execute(
"CREATE INDEX parObjId ON tsk_objects(par_obj_id)");
 
  382                         stmt.execute(
"CREATE INDEX layout_objID ON tsk_file_layout(obj_id)");
 
  385                         stmt.execute(
"CREATE INDEX artifact_objID ON blackboard_artifacts(obj_id)");
 
  386                         stmt.execute(
"CREATE INDEX artifact_artifact_objID ON blackboard_artifacts(artifact_obj_id)");
 
  387                         stmt.execute(
"CREATE INDEX artifact_typeID ON blackboard_artifacts(artifact_type_id)");
 
  388                         stmt.execute(
"CREATE INDEX attrsArtifactID ON blackboard_attributes(artifact_id)");
 
  391                         stmt.execute(
"CREATE INDEX mime_type ON tsk_files(dir_type,mime_type,type)");
 
  392                         stmt.execute(
"CREATE INDEX file_extension ON tsk_files(extension)");
 
  395                         stmt.execute(
"CREATE INDEX relationships_account1 ON account_relationships(account1_id)");
 
  396                         stmt.execute(
"CREATE INDEX relationships_account2 ON account_relationships(account2_id)");
 
  397                         stmt.execute(
"CREATE INDEX relationships_relationship_source_obj_id ON account_relationships(relationship_source_obj_id)");
 
  398                         stmt.execute(
"CREATE INDEX relationships_date_time ON account_relationships(date_time)");
 
  399                         stmt.execute(
"CREATE INDEX relationships_relationship_type ON account_relationships(relationship_type)");
 
  400                         stmt.execute(
"CREATE INDEX relationships_data_source_obj_id ON account_relationships(data_source_obj_id)");
 
  403                         stmt.execute(
"CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id)");
 
  404                         stmt.execute(
"CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id)");
 
  405                         stmt.execute(
"CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id)");
 
  406                         stmt.execute(
"CREATE INDEX events_sub_type_time ON tsk_events(event_type_id,  time)");
 
  407                         stmt.execute(
"CREATE INDEX events_time ON tsk_events(time)");
 
  410                         stmt.execute(
"CREATE INDEX score_significance_priority ON tsk_aggregate_score(significance, priority)");
 
  411                         stmt.execute(
"CREATE INDEX score_datasource_obj_id ON tsk_aggregate_score(data_source_obj_id)");
 
  413                         stmt.execute(
"CREATE INDEX tsk_file_attributes_obj_id ON tsk_file_attributes(obj_id)");
 
  416                         stmt.execute(
"CREATE INDEX tsk_os_accounts_login_name_idx  ON tsk_os_accounts(login_name, db_status, realm_id)");
 
  417                         stmt.execute(
"CREATE INDEX tsk_os_accounts_addr_idx  ON tsk_os_accounts(addr, db_status, realm_id)");
 
  419                         stmt.execute(
"CREATE INDEX tsk_os_account_realms_realm_name_idx  ON tsk_os_account_realms(realm_name)");
 
  420                         stmt.execute(
"CREATE INDEX tsk_os_account_realms_realm_addr_idx  ON tsk_os_account_realms(realm_addr)");
 
  422                 } 
catch (SQLException ex) {
 
  423                         throw new TskCoreException(
"Error initializing db_info tables", ex);
 
  427         private void createIngestTables(Statement stmt) 
throws SQLException {
 
  428                 stmt.execute(
"CREATE TABLE ingest_module_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)");
 
  430                 stmt.execute(
"CREATE TABLE ingest_job_status_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)");
 
  432                 stmt.execute(
"CREATE TABLE ingest_modules (ingest_module_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  433                                 + 
"display_name TEXT NOT NULL, unique_name TEXT UNIQUE NOT NULL, type_id INTEGER NOT NULL, " 
  434                                 + 
"version TEXT NOT NULL, FOREIGN KEY(type_id) REFERENCES ingest_module_types(type_id) ON DELETE CASCADE);");
 
  436                 stmt.execute(
"CREATE TABLE ingest_jobs (ingest_job_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  437                                 + 
"obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, host_name TEXT NOT NULL, " 
  438                                 + 
"start_date_time " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  439                                 + 
"end_date_time " + dbQueryHelper.getBigIntType() + 
" NOT NULL, status_id INTEGER NOT NULL, " 
  440                                 + 
"settings_dir TEXT, FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  441                                 + 
"FOREIGN KEY(status_id) REFERENCES ingest_job_status_types(type_id) ON DELETE CASCADE);");
 
  443                 stmt.execute(
"CREATE TABLE ingest_job_modules (ingest_job_id INTEGER, ingest_module_id INTEGER, " 
  444                                 + 
"pipeline_position INTEGER, PRIMARY KEY(ingest_job_id, ingest_module_id), " 
  445                                 + 
"FOREIGN KEY(ingest_job_id) REFERENCES ingest_jobs(ingest_job_id) ON DELETE CASCADE, " 
  446                                 + 
"FOREIGN KEY(ingest_module_id) REFERENCES ingest_modules(ingest_module_id) ON DELETE CASCADE);");
 
  449         private void createHostTables(Statement stmt) 
throws SQLException {
 
  451                 stmt.execute(
"CREATE TABLE tsk_persons (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  452                                 + 
"name TEXT NOT NULL, "  
  456                 stmt.execute(
"CREATE TABLE tsk_hosts (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  457                                 + 
"name TEXT NOT NULL, "  
  458                                 + 
"db_status INTEGER DEFAULT 0, "  
  459                                 + 
"person_id INTEGER, " 
  460                                 + 
"merged_into " + dbQueryHelper.getBigIntType() + 
", " 
  461                                 + 
"FOREIGN KEY(person_id) REFERENCES tsk_persons(id) ON DELETE SET NULL, " 
  462                                 + 
"FOREIGN KEY(merged_into) REFERENCES tsk_hosts(id) ON DELETE CASCADE, " 
  465                 stmt.execute(
"CREATE TABLE  tsk_host_addresses (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  466                                 + 
"address_type INTEGER NOT NULL, " 
  467                                 + 
"address TEXT NOT NULL, " 
  468                                 + 
"UNIQUE(address_type, address)) ");
 
  470                 stmt.execute(
"CREATE TABLE tsk_host_address_map  (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  471                                 + 
"host_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  472                                 + 
"addr_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  473                                 + 
"source_obj_id " + dbQueryHelper.getBigIntType() + 
", "  
  474                                 + 
"time " + dbQueryHelper.getBigIntType() + 
", "  
  475                                 + 
"UNIQUE(host_id, addr_obj_id, time), " 
  476                                 + 
"FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE, " 
  477                                 + 
"FOREIGN KEY(addr_obj_id) REFERENCES tsk_host_addresses(id), " 
  478                                 + 
"FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL )");
 
  481                 stmt.execute(
"CREATE TABLE tsk_host_address_dns_ip_map (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  482                                 + 
"dns_address_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  483                                 + 
"ip_address_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  484                                 + 
"source_obj_id " + dbQueryHelper.getBigIntType() + 
", " 
  485                                 + 
"time " + dbQueryHelper.getBigIntType() + 
", "  
  486                                 + 
"UNIQUE(dns_address_id, ip_address_id, time), " 
  487                                 + 
"FOREIGN KEY(dns_address_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE, " 
  488                                 + 
"FOREIGN KEY(ip_address_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE," 
  489                                 + 
"FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL )");
 
  492                 stmt.execute(
"CREATE TABLE  tsk_host_address_usage (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  493                                 + 
"addr_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  494                                 + 
"obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, "      
  495                                 + 
"data_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, "  
  496                                 + 
"UNIQUE(addr_obj_id, obj_id), " 
  497                                 + 
"FOREIGN KEY(addr_obj_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE, " 
  498                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  499                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE )");            
 
  503         private void createAccountTables(Statement stmt) 
throws SQLException {
 
  504                 stmt.execute(
"CREATE TABLE account_types (account_type_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  505                                 + 
"type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
 
  508                 stmt.execute(
"CREATE TABLE accounts (account_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  509                                 + 
"account_type_id INTEGER NOT NULL, account_unique_identifier TEXT NOT NULL, " 
  510                                 + 
"UNIQUE(account_type_id, account_unique_identifier), " 
  511                                 + 
"FOREIGN KEY(account_type_id) REFERENCES account_types(account_type_id))");
 
  514                 stmt.execute(
"CREATE TABLE account_relationships (relationship_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  515                                 + 
"account1_id INTEGER NOT NULL, account2_id INTEGER NOT NULL, " 
  516                                 + 
"relationship_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  517                                 + 
"date_time " + dbQueryHelper.getBigIntType() + 
", relationship_type INTEGER NOT NULL, " 
  518                                 + 
"data_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  519                                 + 
"UNIQUE(account1_id, account2_id, relationship_source_obj_id), " 
  520                                 + 
"FOREIGN KEY(account1_id) REFERENCES accounts(account_id), " 
  521                                 + 
"FOREIGN KEY(account2_id) REFERENCES accounts(account_id), " 
  522                                 + 
"FOREIGN KEY(relationship_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  523                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE)");
 
  526                 stmt.execute(
"CREATE TABLE tsk_os_account_realms (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  527                                 + 
"realm_name TEXT DEFAULT NULL, "       
  528                                 + 
"realm_addr TEXT DEFAULT NULL, "               
  529                                 + 
"realm_signature TEXT NOT NULL, "      
  530                                 + 
"scope_host_id " + dbQueryHelper.getBigIntType() + 
" DEFAULT NULL, "  
  531                                 + 
"scope_confidence INTEGER, "   
  532                                 + 
"db_status INTEGER DEFAULT 0, "  
  533                                 + 
"merged_into " + dbQueryHelper.getBigIntType() + 
" DEFAULT NULL, "     
  534                                 + 
"UNIQUE(realm_signature), " 
  535                                 + 
"FOREIGN KEY(scope_host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE," 
  536                                 + 
"FOREIGN KEY(merged_into) REFERENCES tsk_os_account_realms(id) ON DELETE CASCADE )");
 
  539                 stmt.execute(
"CREATE TABLE tsk_os_accounts (os_account_obj_id " + dbQueryHelper.getBigIntType() + 
" PRIMARY KEY, " 
  540                                 + 
"login_name TEXT DEFAULT NULL, "       
  541                                 + 
"full_name TEXT DEFAULT NULL, "        
  542                                 + 
"realm_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, "            
  543                                 + 
"addr TEXT DEFAULT NULL, "     
  544                                 + 
"signature TEXT NOT NULL, "    
  547                                 + 
"created_date " + dbQueryHelper.getBigIntType() + 
" DEFAULT NULL, " 
  548                                 + 
"db_status INTEGER DEFAULT 0, "  
  549                             + 
"merged_into " + dbQueryHelper.getBigIntType() + 
" DEFAULT NULL, " 
  550                                 + 
"UNIQUE(signature, realm_id), " 
  551                                 + 
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  552                                 + 
"FOREIGN KEY(realm_id) REFERENCES tsk_os_account_realms(id) ON DELETE CASCADE," 
  553                                 + 
"FOREIGN KEY(merged_into) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE )");
 
  557         private void createAccountInstancesAndArtifacts(Statement stmt) 
throws SQLException {
 
  560                 stmt.execute(
"CREATE TABLE tsk_os_account_attributes (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  561                                 + 
"os_account_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  562                                 + 
"host_id " + dbQueryHelper.getBigIntType() + 
", "  
  563                                 + 
"source_obj_id " + dbQueryHelper.getBigIntType() + 
", "        
  564                                 + 
"attribute_type_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  565                                 + 
"value_type INTEGER NOT NULL, " 
  566                                 + 
"value_byte " + dbQueryHelper.getBlobType() + 
", " 
  567                                 + 
"value_text TEXT, " 
  568                                 + 
"value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + 
", " 
  569                                 + 
"value_double NUMERIC(20, 10), " 
  570                                 + 
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "  
  571                                 + 
"FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE, " 
  572                                 + 
"FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL, "               
  573                                 + 
"FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");  
 
  576                 stmt.execute(
"CREATE TABLE tsk_os_account_instances (id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  577                                 + 
"os_account_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  578                                 + 
"data_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, "  
  579                                 + 
"instance_type INTEGER NOT NULL, "     
  580                                 + 
"UNIQUE(os_account_obj_id, data_source_obj_id, instance_type), " 
  581                                 + 
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "  
  582                                 + 
"FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE ) ");
 
  585                 stmt.execute(
"CREATE TABLE tsk_data_artifacts ( " 
  586                                 + 
"artifact_obj_id " + dbQueryHelper.getBigIntType() + 
" PRIMARY KEY, " 
  587                                 + 
"os_account_obj_id " + dbQueryHelper.getBigIntType() + 
", " 
  588                                 + 
"FOREIGN KEY(artifact_obj_id) REFERENCES blackboard_artifacts(artifact_obj_id) ON DELETE CASCADE, " 
  589                                 + 
"FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE SET NULL) "); 
 
  592         private void createEventTables(Statement stmt) 
throws SQLException {
 
  593                 stmt.execute(
"CREATE TABLE tsk_event_types (" 
  594                                 + 
" event_type_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY," 
  595                                 + 
" display_name TEXT UNIQUE NOT NULL , " 
  596                                 + 
" super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
 
  611                         "CREATE TABLE tsk_event_descriptions ( " 
  612                         + 
" event_description_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  613                         + 
" full_description TEXT NOT NULL, " 
  614                         + 
" med_description TEXT, " 
  615                         + 
" short_description TEXT," 
  616                         + 
" data_source_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  617                         + 
" content_obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  618                         + 
" artifact_id " + dbQueryHelper.getBigIntType() + 
", " 
  619                         + 
" hash_hit INTEGER NOT NULL, "  
  620                         + 
" tagged INTEGER NOT NULL, "  
  621                         + 
" FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id) ON DELETE CASCADE, " 
  622                         + 
" FOREIGN KEY(content_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, " 
  623                         + 
" FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id) ON DELETE CASCADE," 
  624                         + 
" UNIQUE (full_description, content_obj_id, artifact_id))");
 
  627                         "CREATE TABLE tsk_events (" 
  628                         + 
" event_id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  629                         + 
" event_type_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL REFERENCES tsk_event_types(event_type_id) ," 
  630                         + 
" event_description_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ON DELETE CASCADE ," 
  631                         + 
" time " + dbQueryHelper.getBigIntType() + 
" NOT NULL , " 
  632                         + 
" UNIQUE (event_type_id, event_description_id, time))");                      
 
  635         private void createAttributeTables(Statement stmt) 
throws SQLException {
 
  641                 stmt.execute(
"CREATE TABLE tsk_file_attributes ( id " + dbQueryHelper.getPrimaryKey() + 
" PRIMARY KEY, " 
  642                                 + 
"obj_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  643                                 + 
"attribute_type_id " + dbQueryHelper.getBigIntType() + 
" NOT NULL, " 
  644                                 + 
"value_type INTEGER NOT NULL, value_byte " + dbQueryHelper.getBlobType() + 
", " 
  645                                 + 
"value_text TEXT, value_int32 INTEGER, value_int64 " + dbQueryHelper.getBigIntType() + 
", value_double NUMERIC(20, 10), " 
  646                                 + 
"FOREIGN KEY(obj_id) REFERENCES tsk_files(obj_id) ON DELETE CASCADE, " 
  647                                 + 
"FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
 
  653         private abstract class DbCreationHelper {
 
  660                 abstract void createDatabase() throws TskCoreException;
 
  667                 abstract Connection getConnection() throws TskCoreException;
 
  677                 abstract 
void performPreInitialization(Connection conn) throws TskCoreException;
 
  685                 abstract 
void performPostTableInitialization(Connection conn) throws TskCoreException;
 
  691         private class PostgreSQLDbCreationHelper extends DbCreationHelper {
 
  693                 private final static String JDBC_BASE_URI = 
"jdbc:postgresql://"; 
 
  694                 private final static String JDBC_DRIVER = 
"org.postgresql.Driver"; 
 
  696                 final private String caseName;
 
  697                 final private CaseDbConnectionInfo info;
 
  699                 PostgreSQLDbCreationHelper(String caseName, CaseDbConnectionInfo info) {
 
  700                         this.caseName = caseName;
 
  705                 void createDatabase() throws TskCoreException{
 
  706                         try(Connection conn = getPostgresConnection();
 
  707                                         Statement stmt = conn.createStatement()) {
 
  708                                 stmt.execute(
"CREATE DATABASE \"" + caseName + 
"\" WITH ENCODING='UTF8'");              
 
  709                         } 
catch (SQLException ex) {
 
  710                                 throw new TskCoreException(
"Error creating PostgreSQL case " + caseName, ex);
 
  715                 Connection getConnection() throws TskCoreException {
 
  716                         return getConnection(caseName);
 
  724                 Connection getPostgresConnection() throws TskCoreException {
 
  725                         return getConnection(
"postgres");
 
  735                 Connection getConnection(String databaseName) 
throws TskCoreException {
 
  736                         String encodedDbName;
 
  738                                 encodedDbName = URLEncoder.encode(databaseName, 
"UTF-8");
 
  739                         } 
catch (UnsupportedEncodingException ex) {
 
  741                                 logger.log(Level.WARNING, 
"Error encoding database name " + databaseName, ex);
 
  742                                 encodedDbName = databaseName;
 
  745                         StringBuilder url = 
new StringBuilder();
 
  746                         url.append(JDBC_BASE_URI)
 
  747                                 .append(info.getHost())
 
  749                                 .append(info.getPort())
 
  751                                 .append(encodedDbName);
 
  753                         if (info.isSslEnabled()) {                              
 
  754                                 if (info.isSslVerify()) {
 
  755                                         if (info.getCustomSslValidationClassName().isBlank()) {
 
  756                                                 url.append(SSL_VERIFY_DEFAULT_URL);
 
  759                                                 url.append(getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName()));
 
  762                                         url.append(SSL_NONVERIFY_URL);
 
  768                                 Properties props = 
new Properties();
 
  769                                 props.setProperty(
"user", info.getUserName());     
 
  770                                 props.setProperty(
"password", info.getPassword()); 
 
  772                                 Class.forName(JDBC_DRIVER);
 
  773                                 conn = DriverManager.getConnection(url.toString(), props);
 
  774                         } 
catch (ClassNotFoundException | SQLException ex) {
 
  775                                 throw new TskCoreException(
"Failed to acquire ephemeral connection to PostgreSQL database " + databaseName, ex); 
 
  781                 void performPreInitialization(Connection conn) 
throws TskCoreException {
 
  786                 void performPostTableInitialization(Connection conn) 
throws TskCoreException {
 
  787                         try (Statement stmt = conn.createStatement()) {
 
  788                                 stmt.execute(
"ALTER SEQUENCE blackboard_artifacts_artifact_id_seq minvalue -9223372036854775808 restart with -9223372036854775808");
 
  792                                 stmt.execute(
"CREATE INDEX tsk_files_datasrc_md5_size_partial_index ON tsk_files(data_source_obj_id, md5, size) WHERE md5 IS NOT NULL AND size > 0");
 
  793                         } 
catch (SQLException ex) {
 
  794                                 throw new TskCoreException(
"Error performing PostgreSQL post table initialization", ex);
 
  802         private class SQLiteDbCreationHelper 
extends DbCreationHelper {
 
  804                 private final static String PRAGMA_SYNC_OFF = 
"PRAGMA synchronous = OFF"; 
 
  805                 private final static String PRAGMA_READ_UNCOMMITTED_TRUE = 
"PRAGMA read_uncommitted = True"; 
 
  806                 private final static String PRAGMA_ENCODING_UTF8 = 
"PRAGMA encoding = 'UTF-8'"; 
 
  807                 private final static String PRAGMA_PAGE_SIZE_4096 = 
"PRAGMA page_size = 4096"; 
 
  808                 private final static String PRAGMA_FOREIGN_KEYS_ON = 
"PRAGMA foreign_keys = ON"; 
 
  810                 private final static String JDBC_DRIVER = 
"org.sqlite.JDBC"; 
 
  811         private final static String JDBC_BASE_URI = 
"jdbc:sqlite:"; 
 
  815                 SQLiteDbCreationHelper(String dbPath) {
 
  816                         this.dbPath = dbPath;
 
  820                 void createDatabase() throws TskCoreException {
 
  823                         File dbFile = 
new File(dbPath);
 
  824                         if (dbFile.exists()) {
 
  825                                 throw new TskCoreException(
"Case database already exists : " + dbPath);
 
  828                         if (dbFile.getParentFile() != null && !dbFile.getParentFile().exists()) {
 
  829                                 throw new TskCoreException(
"Case database folder does not exist : " + dbFile.getParent());
 
  834                 Connection getConnection() throws TskCoreException {
 
  836                         StringBuilder url = 
new StringBuilder();
 
  837                         url.append(JDBC_BASE_URI)
 
  842                                 Class.forName(JDBC_DRIVER);
 
  843                                 conn = DriverManager.getConnection(url.toString());
 
  844                         } 
catch (ClassNotFoundException | SQLException ex) {
 
  845                                 throw new TskCoreException(
"Failed to acquire ephemeral connection SQLite database " + dbPath, ex); 
 
  851                 void performPreInitialization(Connection conn) 
throws TskCoreException {
 
  852                         try (Statement stmt = conn.createStatement()) {
 
  853                                 stmt.execute(PRAGMA_SYNC_OFF);
 
  854                                 stmt.execute(PRAGMA_READ_UNCOMMITTED_TRUE);
 
  855                                 stmt.execute(PRAGMA_ENCODING_UTF8);
 
  856                                 stmt.execute(PRAGMA_PAGE_SIZE_4096);
 
  857                                 stmt.execute(PRAGMA_FOREIGN_KEYS_ON);
 
  858                         } 
catch (SQLException ex) {
 
  859                                 throw new TskCoreException(
"Error setting pragmas", ex);
 
  864                 void performPostTableInitialization(Connection conn) 
throws TskCoreException {
 
  865                         try (Statement stmt = conn.createStatement()) {                         
 
  868                                 stmt.execute(
"CREATE INDEX tsk_files_datasrc_md5_size_index ON tsk_files(data_source_obj_id, md5, size)");
 
  869                         } 
catch (SQLException ex) {
 
  870                                 throw new TskCoreException(
"Error performing SQLite post table initialization", ex);