Sleuth Kit Java Bindings (JNI) 4.14.0
Java bindings for using The Sleuth Kit
Loading...
Searching...
No Matches
SleuthkitCase.java
Go to the documentation of this file.
1/*
2 * Sleuth Kit Data Model
3 *
4 * Copyright 2011-2023 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 */
19package org.sleuthkit.datamodel;
20
21import com.google.common.annotations.Beta;
22import com.google.common.cache.Cache;
23import com.google.common.cache.CacheBuilder;
24import com.google.common.collect.ImmutableSet;
25import com.google.common.eventbus.EventBus;
26import com.google.gson.Gson;
27import com.mchange.v2.c3p0.ComboPooledDataSource;
28import com.mchange.v2.c3p0.DataSources;
29import com.mchange.v2.c3p0.PooledDataSource;
30import com.zaxxer.sparsebits.SparseBitSet;
31import java.beans.PropertyVetoException;
32import java.io.BufferedInputStream;
33import java.io.BufferedOutputStream;
34import java.io.File;
35import java.io.FileInputStream;
36import java.io.FileOutputStream;
37import java.io.IOException;
38import java.io.InputStream;
39import java.io.OutputStream;
40import java.io.UnsupportedEncodingException;
41import java.net.InetAddress;
42import java.net.URLEncoder;
43import java.nio.charset.StandardCharsets;
44import java.nio.file.Paths;
45import java.sql.Connection;
46import java.sql.DriverManager;
47import java.sql.PreparedStatement;
48import java.sql.ResultSet;
49import java.sql.SQLException;
50import java.sql.Statement;
51import java.text.SimpleDateFormat;
52import java.util.ArrayList;
53import java.util.Arrays;
54import java.util.Collection;
55import java.util.Collections;
56import java.util.concurrent.atomic.AtomicBoolean;
57import java.util.concurrent.atomic.AtomicInteger;
58import java.util.Date;
59import java.util.EnumMap;
60import java.util.HashMap;
61import java.util.HashSet;
62import java.util.LinkedHashMap;
63import java.util.List;
64import java.util.Map;
65import java.util.MissingResourceException;
66import java.util.Objects;
67import java.util.Properties;
68import java.util.ResourceBundle;
69import java.util.Set;
70import java.util.UUID;
71import java.util.concurrent.CompletableFuture;
72import java.util.concurrent.CountDownLatch;
73import java.util.concurrent.TimeUnit;
74import java.util.concurrent.atomic.AtomicLong;
75import java.util.concurrent.locks.ReentrantLock;
76import java.util.concurrent.locks.ReentrantReadWriteLock;
77import java.util.logging.Level;
78import java.util.logging.Logger;
79import java.util.stream.Collectors;
80import org.apache.commons.lang3.StringUtils;
81import org.postgresql.util.PSQLState;
82import org.sleuthkit.datamodel.Blackboard.BlackboardException;
83import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE;
84import org.sleuthkit.datamodel.BlackboardArtifact.Category;
85import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
86import org.sleuthkit.datamodel.BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE;
87import org.sleuthkit.datamodel.IngestJobInfo.IngestJobStatusType;
88import org.sleuthkit.datamodel.IngestModuleInfo.IngestModuleType;
89import org.sleuthkit.datamodel.SleuthkitJNI.CaseDbHandle.AddImageProcess;
90import org.sleuthkit.datamodel.TimelineManager.TimelineEventAddedEvent;
91import org.sleuthkit.datamodel.TskData.DbType;
92import static org.sleuthkit.datamodel.TskData.DbType.POSTGRESQL;
93import static org.sleuthkit.datamodel.TskData.DbType.SQLITE;
94import org.sleuthkit.datamodel.TskData.FileKnown;
95import org.sleuthkit.datamodel.TskData.ObjectType;
96import org.sleuthkit.datamodel.TskData.TSK_DB_FILES_TYPE_ENUM;
97import org.sleuthkit.datamodel.TskData.TSK_FS_ATTR_TYPE_ENUM;
98import org.sleuthkit.datamodel.TskData.TSK_FS_META_FLAG_ENUM;
99import org.sleuthkit.datamodel.TskData.TSK_FS_META_TYPE_ENUM;
100import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_FLAG_ENUM;
101import org.sleuthkit.datamodel.TskData.TSK_FS_NAME_TYPE_ENUM;
102import org.sqlite.SQLiteConfig;
103import org.sqlite.SQLiteDataSource;
104import org.sqlite.SQLiteJDBCLoader;
105
110public class SleuthkitCase {
111
112 private static final int MAX_DB_NAME_LEN_BEFORE_TIMESTAMP = 47;
113
114 static final CaseDbSchemaVersionNumber CURRENT_DB_SCHEMA_VERSION
115 = new CaseDbSchemaVersionNumber(9, 6);
116
117 private static final long BASE_ARTIFACT_ID = Long.MIN_VALUE; // Artifact ids will start at the lowest negative value
118 private static final Logger logger = Logger.getLogger(SleuthkitCase.class.getName());
119 private static final ResourceBundle bundle = ResourceBundle.getBundle("org.sleuthkit.datamodel.Bundle");
120 private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
121 private static final String SQL_ERROR_CONNECTION_GROUP = "08";
122 // either one of these mean connection was rejected by Postgres server
123 private static final String SQL_CONNECTION_REJECTED = "08004";
124 private static final String UNABLE_TO_VERIFY_SSL = "08006";
125
126 private static final String SQL_ERROR_AUTHENTICATION_GROUP = "28";
127 private static final String SQL_ERROR_PRIVILEGE_GROUP = "42";
128 private static final String SQL_ERROR_RESOURCE_GROUP = "53";
129 private static final String SQL_ERROR_LIMIT_GROUP = "54";
130 private static final String SQL_ERROR_INTERNAL_GROUP = "xx";
131
132 private static final Set<String> CORE_TABLE_NAMES = ImmutableSet.of(
133 "tsk_events",
134 "tsk_event_descriptions",
135 "tsk_event_types",
136 "tsk_db_info",
137 "tsk_objects",
138 "tsk_image_info",
139 "tsk_image_names",
140 "tsk_vs_info",
141 "tsk_vs_parts",
142 "tsk_fs_info",
143 "tsk_file_layout",
144 "tsk_files",
145 "tsk_files_path",
146 "tsk_files_derived",
147 "tsk_files_derived_method",
148 "tag_names",
149 "content_tags",
150 "blackboard_artifact_tags",
151 "blackboard_artifacts",
152 "blackboard_attributes",
153 "blackboard_artifact_types",
154 "blackboard_attribute_types",
155 "data_source_info",
156 "file_encoding_types",
157 "file_collection_status_types",
158 "ingest_module_types",
159 "ingest_job_status_types",
160 "ingest_modules",
161 "ingest_jobs",
162 "ingest_job_modules",
163 "account_types",
164 "accounts",
165 "account_relationships",
166 "review_statuses",
167 "reports,");
168
169 private static final Set<String> CORE_INDEX_NAMES = ImmutableSet.of(
170 "parObjId",
171 "layout_objID",
172 "artifact_objID",
173 "artifact_artifact_objID",
174 "artifact_typeID",
175 "attrsArtifactID",
176 "mime_type",
177 "file_extension",
178 "relationships_account1",
179 "relationships_account2",
180 "relationships_relationship_source_obj_id",
181 "relationships_date_time",
182 "relationships_relationship_type",
183 "relationships_data_source_obj_id",
184 "events_time",
185 "events_type",
186 "events_data_source_obj_id",
187 "events_file_obj_id",
188 "events_artifact_id");
189
190 private static final String TSK_VERSION_KEY = "TSK_VER";
191 private static final String SCHEMA_MAJOR_VERSION_KEY = "SCHEMA_MAJOR_VERSION";
192 private static final String SCHEMA_MINOR_VERSION_KEY = "SCHEMA_MINOR_VERSION";
193 private static final String CREATION_SCHEMA_MAJOR_VERSION_KEY = "CREATION_SCHEMA_MAJOR_VERSION";
194 private static final String CREATION_SCHEMA_MINOR_VERSION_KEY = "CREATION_SCHEMA_MINOR_VERSION";
195
196 // key in acquisition tool settings; the password for decrypting an image
197 static final String IMAGE_PASSWORD_KEY = "imagePassword";
198
199 private final ConnectionPool connections;
200 private final Object carvedFileDirsLock = new Object();
201 private final static int MAX_CARVED_FILES_PER_FOLDER = 2000;
202 private final Map<Long, CarvedFileDirInfo> rootIdsToCarvedFileDirs = new HashMap<>();
203 private final Map<Long, FileSystem> fileSystemIdMap = new HashMap<>(); // Cache for file system files.
204 private final List<ErrorObserver> sleuthkitCaseErrorObservers = new ArrayList<>();
205 private final String databaseName;
206 private final String dbPath;
207 private final DbType dbType;
208 private final String caseDirPath;
209 private SleuthkitJNI.CaseDbHandle caseHandle;
210 private final String caseHandleIdentifier; // Used to identify this case in the JNI cache.
211 private String dbBackupPath;
212 private AtomicBoolean timelineEventsDisabled = new AtomicBoolean(false);
213
214 private CaseDbSchemaVersionNumber caseDBSchemaCreationVersion;
215
216 // Objects for caching the result of isRootDirectory(). Lock is for visibility only.
217 private final Object rootDirectoryMapLock = new Object();
218 private final Map<RootDirectoryKey, Long> rootDirectoryMap = new HashMap<>();
219 private final Cache<Long, Boolean> isRootDirectoryCache
220 = CacheBuilder.newBuilder().maximumSize(200000).expireAfterAccess(5, TimeUnit.MINUTES).build();
221 // custom provider for file bytes (can be null)
222 private final ContentStreamProvider contentProvider;
223 private final LockResources lockResources;
224
225 /*
226 * First parameter is used to specify the SparseBitSet to use, as object IDs
227 * can be larger than the max size of a SparseBitSet
228 */
229 private final Map<Long, SparseBitSet> hasChildrenBitSetMap = new HashMap<>();
230 // Lock to serialize access to the bitset.
231 private final ReentrantLock childrenBitSetLock = new ReentrantLock();
232 // Latch to enforce a happens before relation
233 private final CountDownLatch childrenBitSetInitLatch = new CountDownLatch(1);
234
235
236 private long nextArtifactId; // Used to ensure artifact ids come from the desired range.
237 // This read/write lock is used to implement a layer of locking on top of
238 // the locking protocol provided by the underlying SQLite database. The Java
239 // locking protocol improves performance for reasons that are not currently
240 // understood. Note that the lock is contructed to use a fairness policy.
241 private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(true);
242
243 private CommunicationsManager communicationsMgr;
244 private TimelineManager timelineMgr;
245 private Blackboard blackboard;
246 private CaseDbAccessManager dbAccessManager;
247 private FileManager fileManager;
248 private TaggingManager taggingMgr;
249 private ScoringManager scoringManager;
250 private OsAccountRealmManager osAccountRealmManager;
251 private OsAccountManager osAccountManager;
252 private HostManager hostManager;
253 private PersonManager personManager;
254 private HostAddressManager hostAddressManager;
255
256 private final Map<String, Set<Long>> deviceIdToDatasourceObjIdMap = new HashMap<>();
257
258 private final EventBus eventBus = new EventBus("SleuthkitCase-EventBus");
259
260 public void registerForEvents(Object listener) {
261 eventBus.register(listener);
262 }
263
264 public void unregisterForEvents(Object listener) {
265 eventBus.unregister(listener);
266 }
267
268 void fireTSKEvent(Object event) {
269 eventBus.post(event);
270 }
271
272 // Cache of frequently used content objects (e.g. data source, file system).
273 private final Map<Long, Content> frequentlyUsedContentMap = new HashMap<>();
274
275 private Examiner cachedCurrentExaminer = null;
276
277 static {
278 Properties p = new Properties(System.getProperties());
279 p.put("com.mchange.v2.log.MLog", "com.mchange.v2.log.FallbackMLog");
280 p.put("com.mchange.v2.log.FallbackMLog.DEFAULT_CUTOFF_LEVEL", "SEVERE");
281 System.setProperties(p);
282 }
283
298 public static void tryConnect(CaseDbConnectionInfo info) throws TskCoreException {
299 // Check if we can talk to the database.
300 if (info.getHost() == null || info.getHost().isEmpty()) {
301 throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingHostname")); //NON-NLS
302 } else if (info.getPort() == null || info.getPort().isEmpty()) {
303 throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingPort")); //NON-NLS
304 } else if (info.getUserName() == null || info.getUserName().isEmpty()) {
305 throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingUsername")); //NON-NLS
306 } else if (info.getPassword() == null || info.getPassword().isEmpty()) {
307 throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.MissingPassword")); //NON-NLS
308 }
309
310 try {
311 Class.forName("org.postgresql.Driver"); //NON-NLS
312 String connectionURL = "jdbc:postgresql://" + info.getHost() + ":" + info.getPort() + "/postgres";
313 if (info.isSslEnabled()) {
314 if (info.isSslVerify()) {
315 if (info.getCustomSslValidationClassName().isBlank()) {
316 connectionURL += CaseDatabaseFactory.SSL_VERIFY_DEFAULT_URL;
317 } else {
318 // use custom SSL certificate validation class
319 connectionURL += CaseDatabaseFactory.getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName());
320 }
321 } else {
322 connectionURL += CaseDatabaseFactory.SSL_NONVERIFY_URL;
323 }
324 }
325 Connection conn = DriverManager.getConnection(connectionURL, info.getUserName(), info.getPassword()); //NON-NLS
326 if (conn != null) {
327 conn.close();
328 }
329 } catch (SQLException ex) {
330 String result;
331 String sqlState = ex.getSQLState().toLowerCase();
332 if (sqlState.startsWith(SQL_ERROR_CONNECTION_GROUP)) {
333 if (SQL_CONNECTION_REJECTED.equals(ex.getSQLState())) {
334 if (info.isSslEnabled()) {
335 result = "Server rejected the SSL connection attempt. Check SSL configuration.";
336 } else {
337 result = "Server rejected the connection attempt. Check server configuration.";
338 }
339 } else if (UNABLE_TO_VERIFY_SSL.equals(ex.getSQLState())) {
340 result = "Unable to verify SSL certificates. Check SSL configuration.";
341 } else {
342 try {
343 if (InetAddress.getByName(info.getHost()).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
344 // if we can reach the host, then it's probably port problem
345 result = bundle.getString("DatabaseConnectionCheck.Port"); //NON-NLS
346 } else {
347 result = bundle.getString("DatabaseConnectionCheck.HostnameOrPort"); //NON-NLS
348 }
349 } catch (IOException | MissingResourceException any) {
350 // it may be anything
351 result = bundle.getString("DatabaseConnectionCheck.Everything"); //NON-NLS
352 }
353 }
354 } else if (sqlState.startsWith(SQL_ERROR_AUTHENTICATION_GROUP)) {
355 result = bundle.getString("DatabaseConnectionCheck.Authentication"); //NON-NLS
356 } else if (sqlState.startsWith(SQL_ERROR_PRIVILEGE_GROUP)) {
357 result = bundle.getString("DatabaseConnectionCheck.Access"); //NON-NLS
358 } else if (sqlState.startsWith(SQL_ERROR_RESOURCE_GROUP)) {
359 result = bundle.getString("DatabaseConnectionCheck.ServerDiskSpace"); //NON-NLS
360 } else if (sqlState.startsWith(SQL_ERROR_LIMIT_GROUP)) {
361 result = bundle.getString("DatabaseConnectionCheck.ServerRestart"); //NON-NLS
362 } else if (sqlState.startsWith(SQL_ERROR_INTERNAL_GROUP)) {
363 result = bundle.getString("DatabaseConnectionCheck.InternalServerIssue"); //NON-NLS
364 } else {
365 result = bundle.getString("DatabaseConnectionCheck.Connection"); //NON-NLS
366 }
367 throw new TskCoreException(result);
368 } catch (ClassNotFoundException ex) {
369 throw new TskCoreException(bundle.getString("DatabaseConnectionCheck.Installation")); //NON-NLS
370 }
371 }
372
394 private SleuthkitCase(String dbPath, SleuthkitJNI.CaseDbHandle caseHandle, DbType dbType, ContentStreamProvider contentProvider, String lockingApplicationName, boolean useWAL) throws Exception {
395 Class.forName("org.sqlite.JDBC");
396 this.dbPath = dbPath;
397 this.dbType = dbType;
398 File dbFile = new File(dbPath);
399 this.caseDirPath = dbFile.getParentFile().getAbsolutePath();
400 this.databaseName = dbFile.getName();
401
402 this.lockResources = lockingApplicationName == null
403 ? null
404 : LockResources.tryAcquireFileLock(this.caseDirPath, this.databaseName, lockingApplicationName);
405
406 this.connections = new SQLiteConnections(dbPath, useWAL);
407 this.caseHandle = caseHandle;
408 this.caseHandleIdentifier = caseHandle.getCaseDbIdentifier();
409 this.contentProvider = contentProvider;
410 init();
411 logSQLiteJDBCDriverInfo();
412 }
413
425 private SleuthkitCase(CaseDbConnectionInfo info, String dbName, SleuthkitJNI.CaseDbHandle caseHandle, String caseDirPath, ContentStreamProvider contentProvider) throws Exception {
426 this.dbPath = "";
427 this.databaseName = dbName;
428 this.dbType = info.getDbType();
429 this.caseDirPath = caseDirPath;
430 this.connections = new PostgreSQLConnections(info, dbName);
431 this.caseHandle = caseHandle;
432 this.caseHandleIdentifier = caseHandle.getCaseDbIdentifier();
433 this.contentProvider = contentProvider;
434 this.lockResources = null;
435 init();
436 }
437
438 private void init() throws Exception {
439 blackboard = new Blackboard(this);
440 updateDatabaseSchema(null);
441 try (CaseDbConnection connection = connections.getConnection()) {
442 blackboard.initBlackboardArtifactTypes(connection);
443 blackboard.initBlackboardAttributeTypes(connection);
444 initNextArtifactId(connection);
445 initIngestModuleTypes(connection);
446 initIngestStatusTypes(connection);
447 initReviewStatuses(connection);
448 initEncodingTypes(connection);
449 initCollectedStatusTypes(connection);
450 populateHasChildrenMap(true);
451 updateExaminers(connection);
452 initDBSchemaCreationVersion(connection);
453 }
454
455 fileManager = new FileManager(this);
456 communicationsMgr = new CommunicationsManager(this);
457 timelineMgr = new TimelineManager(this);
458 dbAccessManager = new CaseDbAccessManager(this);
459 taggingMgr = new TaggingManager(this);
460 scoringManager = new ScoringManager(this);
461 osAccountRealmManager = new OsAccountRealmManager(this);
462 osAccountManager = new OsAccountManager(this);
463 hostManager = new HostManager(this);
464 personManager = new PersonManager(this);
465 hostAddressManager = new HostAddressManager(this);
466 }
467
475 ContentStreamProvider getContentProvider() {
476 return this.contentProvider;
477 }
478
484 static Set<String> getCoreTableNames() {
485 return Collections.unmodifiableSet(CORE_TABLE_NAMES);
486 }
487
493 static Set<String> getCoreIndexNames() {
494 return Collections.unmodifiableSet(CORE_INDEX_NAMES);
495 }
496
505 boolean getHasChildren(Content content) {
506
507 try {
508 // Await initialization
509 childrenBitSetInitLatch.await();
510 } catch (InterruptedException ex) {
511 throw new AssertionError("Interrupted Exception awaiting Children bit set initialization", ex); //NON-NLS
512 }
513 childrenBitSetLock.lock();
514 try {
515 long objId = content.getId();
516 long mapIndex = objId / Integer.MAX_VALUE;
517 int mapValue = (int) (objId % Integer.MAX_VALUE);
518
519 if (hasChildrenBitSetMap.containsKey(mapIndex)) {
520 return hasChildrenBitSetMap.get(mapIndex).get(mapValue);
521 }
522 return false;
523
524 } finally {
525 childrenBitSetLock.unlock();
526 }
527 }
528
534 private void setHasChildren(Long objId) {
535 setHasChildren(objId, false);
536 }
537
543 private void setHasChildren(Long objId, boolean initializing) {
544 try {
545 if (!initializing) {
546 // Await initialization
547 childrenBitSetInitLatch.await();
548 }
549 } catch (InterruptedException ex) {
550 throw new AssertionError("Interrupted Exception awaiting Children bit set initialization",ex); //NON-NLS
551 }
552
553 childrenBitSetLock.lock();
554 try {
555 long mapIndex = objId / Integer.MAX_VALUE;
556 int mapValue = (int) (objId % Integer.MAX_VALUE);
557
558 if (hasChildrenBitSetMap.containsKey(mapIndex)) {
559 hasChildrenBitSetMap.get(mapIndex).set(mapValue);
560 } else {
561 SparseBitSet bitSet = new SparseBitSet();
562 bitSet.set(mapValue);
563 hasChildrenBitSetMap.put(mapIndex, bitSet);
564 }
565 } finally {
566 childrenBitSetLock.unlock();
567 }
568 }
569
578 return communicationsMgr;
579 }
580
587 return blackboard;
588 }
589
596 return fileManager;
597 }
598
607 return timelineMgr;
608 }
609
610 /*
611 * Gets the case database access manager for this case.
612 *
613 * @return The per case CaseDbAccessManager object.
614 *
615 * @throws org.sleuthkit.datamodel.TskCoreException
616 */
618 return dbAccessManager;
619 }
620
627 return taggingMgr;
628 }
629
638 return scoringManager;
639 }
640
649 return osAccountRealmManager;
650 }
651
660 return osAccountManager;
661 }
662
671 return hostManager;
672 }
673
682 return personManager;
683 }
684
693 return hostAddressManager;
694 }
695
705 private void initNextArtifactId(CaseDbConnection connection) throws SQLException {
707 try (Statement statement = connection.createStatement()) {
708 ResultSet resultSet = connection.executeQuery(statement, "SELECT MAX(artifact_id) AS max_artifact_id FROM blackboard_artifacts"); //NON-NLS
709 resultSet.next();
710 nextArtifactId = resultSet.getLong("max_artifact_id") + 1;
711 if (nextArtifactId == 1) {
712 nextArtifactId = BASE_ARTIFACT_ID;
713 }
714 } finally {
716 }
717 }
718
726 private void initIngestModuleTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
727 Statement statement = null;
728 ResultSet resultSet = null;
730 try {
731 statement = connection.createStatement();
732 for (IngestModuleType type : IngestModuleType.values()) {
733 try {
734 String query = "INSERT INTO ingest_module_types (type_id, type_name) VALUES (" + type.ordinal() + ", '" + type.toString() + "')"; // NON-NLS
735 if (getDatabaseType().equals(DbType.POSTGRESQL)) {
736 query += " ON CONFLICT ON CONSTRAINT ingest_module_types_pkey DO NOTHING"; // NON-NLS
737 }
738 statement.execute(query);
739 } catch (SQLException ex) {
740 resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM ingest_module_types WHERE type_id = " + type.ordinal() + ";"); //NON-NLS
741 resultSet.next();
742 if (resultSet.getLong("count") == 0) {
743 throw ex;
744 }
745 resultSet.close();
746 resultSet = null;
747 }
748 }
749 } finally {
750 closeResultSet(resultSet);
751 closeStatement(statement);
753 }
754 }
755
763 private void initIngestStatusTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
764 Statement statement = null;
765 ResultSet resultSet = null;
767 try {
768 statement = connection.createStatement();
769 for (IngestJobStatusType type : IngestJobStatusType.values()) {
770 try {
771 String query = "INSERT INTO ingest_job_status_types (type_id, type_name) VALUES (" + type.ordinal() + ", '" + type.toString() + "')"; // NON-NLS
772 if (getDatabaseType().equals(DbType.POSTGRESQL)) {
773 query += " ON CONFLICT ON CONSTRAINT ingest_job_status_types_pkey DO NOTHING"; // NON-NLS
774 }
775 statement.execute(query);
776 } catch (SQLException ex) {
777 resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM ingest_job_status_types WHERE type_id = " + type.ordinal() + ";"); //NON-NLS
778 resultSet.next();
779 if (resultSet.getLong("count") == 0) {
780 throw ex;
781 }
782 resultSet.close();
783 resultSet = null;
784 }
785 }
786 } finally {
787 closeResultSet(resultSet);
788 closeStatement(statement);
790 }
791 }
792
799 private void initReviewStatuses(CaseDbConnection connection) throws SQLException, TskCoreException {
800 Statement statement = null;
801 ResultSet resultSet = null;
803 try {
804 statement = connection.createStatement();
805 for (BlackboardArtifact.ReviewStatus status : BlackboardArtifact.ReviewStatus.values()) {
806 try {
807 String query = "INSERT INTO review_statuses (review_status_id, review_status_name, display_name) " //NON-NLS
808 + "VALUES (" + status.getID() + ",'" + status.getName() + "','" + status.getDisplayName() + "')";
809 if (getDatabaseType().equals(DbType.POSTGRESQL)) {
810 query += " ON CONFLICT ON CONSTRAINT review_statuses_pkey DO NOTHING"; // NON-NLS
811 }
812 statement.execute(query);
813 } catch (SQLException ex) {
814 resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM review_statuses WHERE review_status_id = " + status.getID()); //NON-NLS
815 resultSet.next();
816 if (resultSet.getLong("count") == 0) {
817 throw ex;
818 }
819 resultSet.close();
820 resultSet = null;
821 }
822 }
823 } finally {
824 closeResultSet(resultSet);
825 closeStatement(statement);
827 }
828 }
829
837 private void initEncodingTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
838 Statement statement = null;
839 ResultSet resultSet = null;
841 try {
842 statement = connection.createStatement();
843 for (TskData.EncodingType type : TskData.EncodingType.values()) {
844 try {
845 String query = "INSERT INTO file_encoding_types (encoding_type, name) VALUES (" + type.getType() + " , '" + type.name() + "')"; // NON-NLS
846 if (getDatabaseType().equals(DbType.POSTGRESQL)) {
847 query += " ON CONFLICT ON CONSTRAINT file_encoding_types_pkey DO NOTHING"; // NON-NLS
848 }
849 statement.execute(query);
850 } catch (SQLException ex) {
851 resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM file_encoding_types WHERE encoding_type = " + type.getType()); //NON-NLS
852 resultSet.next();
853 if (resultSet.getLong("count") == 0) {
854 throw ex;
855 }
856 resultSet.close();
857 resultSet = null;
858 }
859 }
860 } finally {
861 closeResultSet(resultSet);
862 closeStatement(statement);
864 }
865 }
866
874 private void initCollectedStatusTypes(CaseDbConnection connection) throws SQLException, TskCoreException {
875 Statement statement = null;
876 ResultSet resultSet = null;
878 try {
879 statement = connection.createStatement();
880 for (TskData.CollectedStatus type : TskData.CollectedStatus.values()) {
881 try {
882 String query = "INSERT INTO file_collection_status_types (collection_status_type, name) VALUES (" + type.getType() + " , '" + type.name() + "')"; // NON-NLS
883 if (getDatabaseType().equals(DbType.POSTGRESQL)) {
884 query += " ON CONFLICT ON CONSTRAINT file_collection_status_types_pkey DO NOTHING"; // NON-NLS
885 }
886 statement.execute(query);
887 } catch (SQLException ex) {
888 resultSet = connection.executeQuery(statement, "SELECT COUNT(*) as count FROM file_collection_status_types WHERE collection_status_type = " + type.getType()); //NON-NLS
889 resultSet.next();
890 if (resultSet.getLong("count") == 0) {
891 throw ex;
892 }
893 resultSet.close();
894 resultSet = null;
895 }
896 }
897 } finally {
898 closeResultSet(resultSet);
899 closeStatement(statement);
901 }
902 }
903
912 private void updateExaminers(CaseDbConnection connection) throws SQLException, TskCoreException {
913
914 String loginName = System.getProperty("user.name");
915 if (loginName.isEmpty()) {
916 logger.log(Level.SEVERE, "Cannot determine logged in user name");
917 return;
918 }
919
921 try {
922 PreparedStatement statement;
923 switch (getDatabaseType()) {
924 case POSTGRESQL:
925 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_EXAMINER_POSTGRESQL);
926 break;
927 case SQLITE:
928 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_EXAMINER_SQLITE);
929 break;
930 default:
931 throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
932 }
933 statement.clearParameters();
934 statement.setString(1, loginName);
935 connection.executeUpdate(statement);
936 } catch (SQLException ex) {
937 throw new TskCoreException("Error inserting row in tsk_examiners. login name: " + loginName, ex);
938 } finally {
940 }
941 }
942
948 private void populateHasChildrenMap(boolean async) throws TskCoreException {
949
950 Runnable childrenBitSetLockInitRunnable = () -> {
951
957 childrenBitSetLock.lock();
958 // The distinct parent objeect id lookup is expensive in postgresql
959 // This is offloaded into a thread and the incident open proceeds.
960 // The access to the results are guarded by an object lock on hasChildrenBitSetMap.
961 // The issue with this approach is that the SQLException will not cause a TSKCOreException.
962 // Since this is running async, it also acquires a new connection from the pool
963
964 long timestamp = System.currentTimeMillis();
965
966 Statement statement = null;
967 ResultSet resultSet = null;
969 try (CaseDbConnection neoConnection = connections.getConnection()) {
970 statement = neoConnection.createStatement();
971 String query = "select distinct par_obj_id from tsk_objects";
972 if (dbType == DbType.POSTGRESQL) {
973 query = "select distinct ON (par_obj_id) par_obj_id from tsk_objects";
974 }
975
976 resultSet = statement.executeQuery(query); //NON-NLS
977
981 while (resultSet.next()) {
982 setHasChildren(resultSet.getLong("par_obj_id"), true);
983 }
984
985 long delay = System.currentTimeMillis() - timestamp;
986 logger.log(Level.INFO, "Time to initialize parent node cache: {0} ms", delay); //NON-NLS
987 } catch (SQLException ex) {
988 logger.log(Level.SEVERE, "Error populating parent node cache", ex); //NON-NLS
989 // Dont really expect this to be thrown, but if this happens, then it is non-recoverable.
990 throw new AssertionError("Error populating parent node cache",ex); //NON-NLS
991 } catch (TskCoreException ex) {
992 logger.log(Level.SEVERE, "Error acquiring connection", ex); //NON-NLS
993 throw new AssertionError("Error acquiring connection",ex); //NON-NLS
994 } finally {
995 closeResultSet(resultSet);
996 closeStatement(statement);
998 childrenBitSetLock.unlock();
999 // Countdown the latch as initialization has completed.
1000 childrenBitSetInitLatch.countDown();
1001 }
1002 };
1003
1004 if (async) {
1005 CompletableFuture.runAsync(childrenBitSetLockInitRunnable);
1006 } else {
1007 childrenBitSetLockInitRunnable.run();
1008 }
1009 }
1010
1017 void addDataSourceToHasChildrenMap() throws TskCoreException {
1018 try {
1019 // Await initialization. ensure no async version of the init is still running.
1020 childrenBitSetInitLatch.await();
1021 } catch (InterruptedException ex) {
1022 throw new AssertionError("Interrupted Exception awaiting Children bit set initialization", ex); //NON-NLS
1023 }
1024 populateHasChildrenMap(false);
1025 }
1026
1036 private void updateDatabaseSchema(String dbPath) throws Exception {
1037 CaseDbConnection connection = null;
1038 ResultSet resultSet = null;
1039 Statement statement = null;
1041 try {
1042 connection = connections.getConnection();
1043 connection.beginTransaction();
1044
1045 boolean hasMinorVersion = false;
1046 ResultSet columns = connection.getConnection().getMetaData().getColumns(null, null, "tsk_db_info", "schema%");
1047 while (columns.next()) {
1048 if (columns.getString("COLUMN_NAME").equals("schema_minor_ver")) {
1049 hasMinorVersion = true;
1050 }
1051 }
1052
1053 // Get the schema version number of the case database from the tsk_db_info table.
1054 int dbSchemaMajorVersion;
1055 int dbSchemaMinorVersion = 0; //schemas before 7 have no minor version , default it to zero.
1056
1057 statement = connection.createStatement();
1058 resultSet = connection.executeQuery(statement, "SELECT schema_ver"
1059 + (hasMinorVersion ? ", schema_minor_ver" : "")
1060 + " FROM tsk_db_info"); //NON-NLS
1061 if (resultSet.next()) {
1062 dbSchemaMajorVersion = resultSet.getInt("schema_ver"); //NON-NLS
1063 if (hasMinorVersion) {
1064 //if there is a minor version column, use it, else default to zero.
1065 dbSchemaMinorVersion = resultSet.getInt("schema_minor_ver"); //NON-NLS
1066 }
1067 } else {
1068 throw new TskCoreException();
1069 }
1070 CaseDbSchemaVersionNumber dbSchemaVersion = new CaseDbSchemaVersionNumber(dbSchemaMajorVersion, dbSchemaMinorVersion);
1071
1072 resultSet.close();
1073 resultSet = null;
1074 statement.close();
1075 statement = null;
1076 //check schema compatibility
1077 if (false == CURRENT_DB_SCHEMA_VERSION.isCompatible(dbSchemaVersion)) {
1078 //we cannot open a db with a major schema version higher than the current one.
1079 throw new TskUnsupportedSchemaVersionException(
1080 "Unsupported DB schema version " + dbSchemaVersion + ", the highest supported schema version is " + CURRENT_DB_SCHEMA_VERSION.getMajor() + ".X");
1081 } else if (dbSchemaVersion.compareTo(CURRENT_DB_SCHEMA_VERSION) < 0) {
1082 //The schema version is compatible,possibly after upgrades.
1083
1084 if (null != dbPath) {
1085 // Make a backup copy of the database. Client code can get the path of the backup
1086 // using the getBackupDatabasePath() method.
1087 String backupFilePath = dbPath + ".schemaVer" + dbSchemaVersion.toString() + ".backup"; //NON-NLS
1088 copyCaseDB(backupFilePath);
1089 dbBackupPath = backupFilePath;
1090 }
1091
1092 // ***CALL SCHEMA UPDATE METHODS HERE***
1093 // Each method should examine the schema version passed to it and either:
1094 // a. do nothing and return the schema version unchanged, or
1095 // b. upgrade the database and return the schema version that the db was upgraded to.
1096 dbSchemaVersion = updateFromSchema2toSchema3(dbSchemaVersion, connection);
1097 dbSchemaVersion = updateFromSchema3toSchema4(dbSchemaVersion, connection);
1098 dbSchemaVersion = updateFromSchema4toSchema5(dbSchemaVersion, connection);
1099 dbSchemaVersion = updateFromSchema5toSchema6(dbSchemaVersion, connection);
1100 dbSchemaVersion = updateFromSchema6toSchema7(dbSchemaVersion, connection);
1101 dbSchemaVersion = updateFromSchema7toSchema7dot1(dbSchemaVersion, connection);
1102 dbSchemaVersion = updateFromSchema7dot1toSchema7dot2(dbSchemaVersion, connection);
1103 dbSchemaVersion = updateFromSchema7dot2toSchema8dot0(dbSchemaVersion, connection);
1104 dbSchemaVersion = updateFromSchema8dot0toSchema8dot1(dbSchemaVersion, connection);
1105 dbSchemaVersion = updateFromSchema8dot1toSchema8dot2(dbSchemaVersion, connection);
1106 dbSchemaVersion = updateFromSchema8dot2toSchema8dot3(dbSchemaVersion, connection);
1107 dbSchemaVersion = updateFromSchema8dot3toSchema8dot4(dbSchemaVersion, connection);
1108 dbSchemaVersion = updateFromSchema8dot4toSchema8dot5(dbSchemaVersion, connection);
1109 dbSchemaVersion = updateFromSchema8dot5toSchema8dot6(dbSchemaVersion, connection);
1110 dbSchemaVersion = updateFromSchema8dot6toSchema9dot0(dbSchemaVersion, connection);
1111 dbSchemaVersion = updateFromSchema9dot0toSchema9dot1(dbSchemaVersion, connection);
1112 dbSchemaVersion = updateFromSchema9dot1toSchema9dot2(dbSchemaVersion, connection);
1113 dbSchemaVersion = updateFromSchema9dot2toSchema9dot3(dbSchemaVersion, connection);
1114 dbSchemaVersion = updateFromSchema9dot3toSchema9dot4(dbSchemaVersion, connection);
1115 dbSchemaVersion = updateFromSchema9dot4toSchema9dot5(dbSchemaVersion, connection);
1116 dbSchemaVersion = updateFromSchema9dot5toSchema9dot6(dbSchemaVersion, connection);
1117
1118
1119 statement = connection.createStatement();
1120 connection.executeUpdate(statement, "UPDATE tsk_db_info SET schema_ver = " + dbSchemaVersion.getMajor() + ", schema_minor_ver = " + dbSchemaVersion.getMinor()); //NON-NLS
1121 connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value = " + dbSchemaVersion.getMajor() + " WHERE name = '" + SCHEMA_MAJOR_VERSION_KEY + "'"); //NON-NLS
1122 connection.executeUpdate(statement, "UPDATE tsk_db_info_extended SET value = " + dbSchemaVersion.getMinor() + " WHERE name = '" + SCHEMA_MINOR_VERSION_KEY + "'"); //NON-NLS
1123 statement.close();
1124 statement = null;
1125 }
1126
1127 connection.commitTransaction();
1128 } catch (Exception ex) { // Cannot do exception multi-catch in Java 6, so use catch-all.
1129 rollbackTransaction(connection);
1130 throw ex;
1131 } finally {
1132 closeResultSet(resultSet);
1133 closeStatement(statement);
1134 closeConnection(connection);
1136 }
1137 }
1138
1146 private void initDBSchemaCreationVersion(CaseDbConnection connection) throws SQLException {
1147
1148 Statement statement = null;
1149 ResultSet resultSet = null;
1150 String createdSchemaMajorVersion = "0";
1151 String createdSchemaMinorVersion = "0";
1153 try {
1154 statement = connection.createStatement();
1155 resultSet = connection.executeQuery(statement, "SELECT name, value FROM tsk_db_info_extended");
1156 while (resultSet.next()) {
1157 String name = resultSet.getString("name");
1158 if (name.equals(CREATION_SCHEMA_MAJOR_VERSION_KEY) || name.equals("CREATED_SCHEMA_MAJOR_VERSION")) {
1159 createdSchemaMajorVersion = resultSet.getString("value");
1160 } else if (name.equals(CREATION_SCHEMA_MINOR_VERSION_KEY) || name.equals("CREATED_SCHEMA_MINOR_VERSION")) {
1161 createdSchemaMinorVersion = resultSet.getString("value");
1162 }
1163 }
1164
1165 } finally {
1166 closeResultSet(resultSet);
1167 closeStatement(statement);
1169 }
1170
1171 caseDBSchemaCreationVersion = new CaseDbSchemaVersionNumber(Integer.parseInt(createdSchemaMajorVersion), Integer.parseInt(createdSchemaMinorVersion));
1172 }
1173
1183 public void copyCaseDB(String newDBPath) throws IOException {
1184 if (dbPath.isEmpty()) {
1185 throw new IOException("Copying case database files is not supported for this type of case database"); //NON-NLS
1186 }
1187
1189 try(InputStream inFile = new FileInputStream(dbPath);
1190 InputStream in = new BufferedInputStream(inFile);
1191 OutputStream outFile = new FileOutputStream(newDBPath);
1192 OutputStream out = new BufferedOutputStream(outFile);) {
1193
1194 int bytesRead = in.read();
1195 while (bytesRead != -1) {
1196 out.write(bytesRead);
1197 bytesRead = in.read();
1198 }
1199 } finally {
1201 }
1202 }
1203
1207 private void logSQLiteJDBCDriverInfo() {
1208 try {
1209 SleuthkitCase.logger.info(String.format("sqlite-jdbc version %s loaded in %s mode", //NON-NLS
1210 SQLiteJDBCLoader.getVersion(), SQLiteJDBCLoader.isNativeMode()
1211 ? "native" : "pure-java")); //NON-NLS
1212 } catch (Exception ex) {
1213 SleuthkitCase.logger.log(Level.SEVERE, "Error querying case database mode", ex);
1214 }
1215 }
1216
1230 @SuppressWarnings("deprecation")
1231 private CaseDbSchemaVersionNumber updateFromSchema2toSchema3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1232 if (schemaVersion.getMajor() != 2) {
1233 return schemaVersion;
1234 }
1235 Statement statement = null;
1236 Statement statement2 = null;
1237 Statement updateStatement = null;
1238 ResultSet resultSet = null;
1240 try {
1241 statement = connection.createStatement();
1242 statement2 = connection.createStatement();
1243
1244 // Add new tables for tags.
1245 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
1246 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
1247 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
1248
1249 // Add a new table for reports.
1250 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
1251
1252 // Add new columns to the image info table.
1253 statement.execute("ALTER TABLE tsk_image_info ADD COLUMN size INTEGER;"); //NON-NLS
1254 statement.execute("ALTER TABLE tsk_image_info ADD COLUMN md5 TEXT;"); //NON-NLS
1255 statement.execute("ALTER TABLE tsk_image_info ADD COLUMN display_name TEXT;"); //NON-NLS
1256
1257 // Add a new column to the file system info table.
1258 statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN display_name TEXT;"); //NON-NLS
1259
1260 // Add a new column to the file table.
1261 statement.execute("ALTER TABLE tsk_files ADD COLUMN meta_seq INTEGER;"); //NON-NLS
1262
1263 // Add new columns and indexes to the attributes table and populate the
1264 // new column. Note that addition of the new column is a denormalization
1265 // to optimize attribute queries.
1266 statement.execute("ALTER TABLE blackboard_attributes ADD COLUMN artifact_type_id INTEGER NULL NOT NULL DEFAULT -1;"); //NON-NLS
1267 statement.execute("CREATE INDEX attribute_artifactTypeId ON blackboard_attributes(artifact_type_id);"); //NON-NLS
1268 statement.execute("CREATE INDEX attribute_valueText ON blackboard_attributes(value_text);"); //NON-NLS
1269 statement.execute("CREATE INDEX attribute_valueInt32 ON blackboard_attributes(value_int32);"); //NON-NLS
1270 statement.execute("CREATE INDEX attribute_valueInt64 ON blackboard_attributes(value_int64);"); //NON-NLS
1271 statement.execute("CREATE INDEX attribute_valueDouble ON blackboard_attributes(value_double);"); //NON-NLS
1272 resultSet = statement.executeQuery("SELECT attrs.artifact_id AS artifact_id, " //NON-NLS
1273 + "arts.artifact_type_id AS artifact_type_id " //NON-NLS
1274 + "FROM blackboard_attributes AS attrs " //NON-NLS
1275 + "INNER JOIN blackboard_artifacts AS arts " //NON-NLS
1276 + "WHERE attrs.artifact_id = arts.artifact_id;"); //NON-NLS
1277 updateStatement = connection.createStatement();
1278 while (resultSet.next()) {
1279 long artifactId = resultSet.getLong("artifact_id");
1280 int artifactTypeId = resultSet.getInt("artifact_type_id");
1281 updateStatement.executeUpdate(
1282 "UPDATE blackboard_attributes " //NON-NLS
1283 + "SET artifact_type_id = " + artifactTypeId //NON-NLS
1284 + " WHERE blackboard_attributes.artifact_id = " + artifactId + ";"); //NON-NLS
1285 }
1286 resultSet.close();
1287
1288 // Convert existing tag artifact and attribute rows to rows in the new tags tables.
1289 Map<String, Long> tagNames = new HashMap<>();
1290 long tagNameCounter = 1;
1291
1292 // Convert file tags.
1293 // We need data from the TSK_TAG_NAME and TSK_COMMENT attributes, and need the file size from the tsk_files table.
1294 resultSet = statement.executeQuery("SELECT * FROM \n"
1295 + "(SELECT blackboard_artifacts.obj_id AS objId, blackboard_attributes.artifact_id AS artifactId, blackboard_attributes.value_text AS name\n"
1296 + "FROM blackboard_artifacts INNER JOIN blackboard_attributes \n"
1297 + "ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id \n"
1298 + "WHERE blackboard_artifacts.artifact_type_id = "
1299 + BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1300 + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()
1301 + ") AS tagNames \n"
1302 + "INNER JOIN \n"
1303 + "(SELECT tsk_files.obj_id as objId2, tsk_files.size AS fileSize \n"
1304 + "FROM blackboard_artifacts INNER JOIN tsk_files \n"
1305 + "ON blackboard_artifacts.obj_id = tsk_files.obj_id) AS fileData \n"
1306 + "ON tagNames.objId = fileData.objId2 \n"
1307 + "LEFT JOIN \n"
1308 + "(SELECT value_text AS comment, artifact_id AS tagArtifactId FROM blackboard_attributes WHERE attribute_type_id = "
1309 + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID() + ") AS tagComments \n"
1310 + "ON tagNames.artifactId = tagComments.tagArtifactId");
1311
1312 while (resultSet.next()) {
1313 long objId = resultSet.getLong("objId");
1314 long fileSize = resultSet.getLong("fileSize");
1315 String tagName = resultSet.getString("name");
1316 String tagComment = resultSet.getString("comment");
1317 if (tagComment == null) {
1318 tagComment = "";
1319 }
1320
1321 if (tagName != null && !tagName.isEmpty()) {
1322 // Get the index for the tag name, adding it to the database if needed.
1323 long tagNameIndex;
1324 if (tagNames.containsKey(tagName)) {
1325 tagNameIndex = tagNames.get(tagName);
1326 } else {
1327 statement2.execute("INSERT INTO tag_names (display_name, description, color) "
1328 + "VALUES(\"" + tagName + "\", \"\", \"None\")");
1329 tagNames.put(tagName, tagNameCounter);
1330 tagNameIndex = tagNameCounter;
1331 tagNameCounter++;
1332 }
1333
1334 statement2.execute("INSERT INTO content_tags (obj_id, tag_name_id, comment, begin_byte_offset, end_byte_offset) "
1335 + "VALUES(" + objId + ", " + tagNameIndex + ", \"" + tagComment + "\", 0, " + fileSize + ")");
1336 }
1337 }
1338 resultSet.close();
1339
1340 // Convert artifact tags.
1341 // We need data from the TSK_TAG_NAME, TSK_TAGGED_ARTIFACT, and TSK_COMMENT attributes.
1342 resultSet = statement.executeQuery("SELECT * FROM \n"
1343 + "(SELECT blackboard_artifacts.obj_id AS objId, blackboard_attributes.artifact_id AS artifactId, "
1344 + "blackboard_attributes.value_text AS name\n"
1345 + "FROM blackboard_artifacts INNER JOIN blackboard_attributes \n"
1346 + "ON blackboard_artifacts.artifact_id = blackboard_attributes.artifact_id \n"
1347 + "WHERE blackboard_artifacts.artifact_type_id = "
1348 + BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID()
1349 + " AND blackboard_attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAG_NAME.getTypeID()
1350 + ") AS tagNames \n"
1351 + "INNER JOIN \n"
1352 + "(SELECT value_int64 AS taggedArtifactId, artifact_id AS associatedArtifactId FROM blackboard_attributes WHERE attribute_type_id = "
1353 + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_TAGGED_ARTIFACT.getTypeID() + ") AS tagArtifacts \n"
1354 + "ON tagNames.artifactId = tagArtifacts.associatedArtifactId \n"
1355 + "LEFT JOIN \n"
1356 + "(SELECT value_text AS comment, artifact_id AS commentArtifactId FROM blackboard_attributes WHERE attribute_type_id = "
1357 + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT.getTypeID() + ") AS tagComments \n"
1358 + "ON tagNames.artifactId = tagComments.commentArtifactId");
1359
1360 while (resultSet.next()) {
1361 long artifactId = resultSet.getLong("taggedArtifactId");
1362 String tagName = resultSet.getString("name");
1363 String tagComment = resultSet.getString("comment");
1364 if (tagComment == null) {
1365 tagComment = "";
1366 }
1367 if (tagName != null && !tagName.isEmpty()) {
1368 // Get the index for the tag name, adding it to the database if needed.
1369 long tagNameIndex;
1370 if (tagNames.containsKey(tagName)) {
1371 tagNameIndex = tagNames.get(tagName);
1372 } else {
1373 statement2.execute("INSERT INTO tag_names (display_name, description, color) "
1374 + "VALUES(\"" + tagName + "\", \"\", \"None\")");
1375 tagNames.put(tagName, tagNameCounter);
1376 tagNameIndex = tagNameCounter;
1377 tagNameCounter++;
1378 }
1379
1380 statement2.execute("INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment) "
1381 + "VALUES(" + artifactId + ", " + tagNameIndex + ", \"" + tagComment + "\")");
1382 }
1383 }
1384 resultSet.close();
1385
1386 statement.execute(
1387 "DELETE FROM blackboard_attributes WHERE artifact_id IN " //NON-NLS
1388 + "(SELECT artifact_id FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS
1389 + ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1390 + " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ");"); //NON-NLS
1391 statement.execute(
1392 "DELETE FROM blackboard_artifacts WHERE artifact_type_id = " //NON-NLS
1393 + ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID()
1394 + " OR artifact_type_id = " + ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ";"); //NON-NLS
1395
1396 return new CaseDbSchemaVersionNumber(3, 0);
1397 } finally {
1398 closeStatement(updateStatement);
1399 closeResultSet(resultSet);
1400 closeStatement(statement);
1401 closeStatement(statement2);
1403 }
1404 }
1405
1419 private CaseDbSchemaVersionNumber updateFromSchema3toSchema4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1420 if (schemaVersion.getMajor() != 3) {
1421 return schemaVersion;
1422 }
1423
1424 Statement statement = null;
1425 ResultSet resultSet = null;
1426 Statement queryStatement = null;
1427 ResultSet queryResultSet = null;
1428 Statement updateStatement = null;
1430 try {
1431 // Add mime_type column to tsk_files table. Populate with general
1432 // info artifact file signature data.
1433 statement = connection.createStatement();
1434 updateStatement = connection.createStatement();
1435 statement.execute("ALTER TABLE tsk_files ADD COLUMN mime_type TEXT;");
1436 resultSet = statement.executeQuery("SELECT files.obj_id AS obj_id, attrs.value_text AS value_text "
1437 + "FROM tsk_files AS files, blackboard_attributes AS attrs, blackboard_artifacts AS arts "
1438 + "WHERE files.obj_id = arts.obj_id AND "
1439 + "arts.artifact_id = attrs.artifact_id AND "
1440 + "arts.artifact_type_id = 1 AND "
1441 + "attrs.attribute_type_id = 62");
1442 while (resultSet.next()) {
1443 updateStatement.executeUpdate(
1444 "UPDATE tsk_files " //NON-NLS
1445 + "SET mime_type = '" + resultSet.getString("value_text") + "' " //NON-NLS
1446 + "WHERE tsk_files.obj_id = " + resultSet.getInt("obj_id") + ";"); //NON-NLS
1447 }
1448 resultSet.close();
1449
1450 // Add value_type column to blackboard_attribute_types table.
1451 statement.execute("ALTER TABLE blackboard_attribute_types ADD COLUMN value_type INTEGER NOT NULL DEFAULT -1;");
1452 resultSet = statement.executeQuery("SELECT * FROM blackboard_attribute_types AS types"); //NON-NLS
1453 while (resultSet.next()) {
1454 int attributeTypeId = resultSet.getInt("attribute_type_id");
1455 String attributeLabel = resultSet.getString("type_name");
1456 if (attributeTypeId < Blackboard.MIN_USER_DEFINED_TYPE_ID) {
1457 updateStatement.executeUpdate(
1458 "UPDATE blackboard_attribute_types " //NON-NLS
1459 + "SET value_type = " + ATTRIBUTE_TYPE.fromLabel(attributeLabel).getValueType().getType() + " " //NON-NLS
1460 + "WHERE blackboard_attribute_types.attribute_type_id = " + attributeTypeId + ";"); //NON-NLS
1461 }
1462 }
1463 resultSet.close();
1464
1465 // Add a data_sources_info table.
1466 queryStatement = connection.createStatement();
1467 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));");
1468 resultSet = statement.executeQuery("SELECT * FROM tsk_objects WHERE par_obj_id IS NULL");
1469 while (resultSet.next()) {
1470 long objectId = resultSet.getLong("obj_id");
1471 String timeZone = "";
1472 queryResultSet = queryStatement.executeQuery("SELECT tzone FROM tsk_image_info WHERE obj_id = " + objectId);
1473 if (queryResultSet.next()) {
1474 timeZone = queryResultSet.getString("tzone");
1475 }
1476 queryResultSet.close();
1477 updateStatement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone) "
1478 + "VALUES(" + objectId + ", '" + UUID.randomUUID().toString() + "' , '" + timeZone + "');");
1479 }
1480 resultSet.close();
1481
1482 // Add data_source_obj_id column to the tsk_files table.
1483 //
1484 // NOTE: A new case database will have the following FK constraint:
1485 //
1486 // REFERENCES data_source_info (obj_id)
1487 //
1488 // The constraint is sacrificed here to avoid having to create and
1489 // populate a new tsk_files table.
1490 //
1491 // TODO: Do this right.
1492 statement.execute("ALTER TABLE tsk_files ADD COLUMN data_source_obj_id BIGINT NOT NULL DEFAULT -1;");
1493 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");
1494 while (resultSet.next()) {
1495 long fileId = resultSet.getLong("obj_id");
1496 long dataSourceId = getDataSourceObjectId(connection, fileId);
1497 updateStatement.executeUpdate("UPDATE tsk_files SET data_source_obj_id = " + dataSourceId + " WHERE obj_id = " + fileId + ";");
1498 }
1499 resultSet.close();
1500 statement.execute("CREATE TABLE ingest_module_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)"); //NON-NLS
1501 statement.execute("CREATE TABLE ingest_job_status_types (type_id INTEGER PRIMARY KEY, type_name TEXT NOT NULL)"); //NON-NLS
1502 if (this.dbType.equals(DbType.SQLITE)) {
1503 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
1504 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
1505 } else {
1506 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
1507 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
1508 }
1509
1510 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
1511 initIngestModuleTypes(connection);
1512 initIngestStatusTypes(connection);
1513
1514 return new CaseDbSchemaVersionNumber(4, 0);
1515
1516 } finally {
1517 closeResultSet(queryResultSet);
1518 closeStatement(queryStatement);
1519 closeStatement(updateStatement);
1520 closeResultSet(resultSet);
1521 closeStatement(statement);
1523 }
1524 }
1525
1539 private CaseDbSchemaVersionNumber updateFromSchema4toSchema5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1540 if (schemaVersion.getMajor() != 4) {
1541 return schemaVersion;
1542 }
1543
1544 Statement statement = null;
1546 try {
1547 // Add the review_statuses lookup table.
1548 statement = connection.createStatement();
1549 statement.execute("CREATE TABLE review_statuses (review_status_id INTEGER PRIMARY KEY, review_status_name TEXT NOT NULL, display_name TEXT NOT NULL)");
1550
1551 /*
1552 * Add review_status_id column to artifacts table.
1553 *
1554 * NOTE: For DBs created with schema 5 we define a foreign key
1555 * constraint on the review_status_column. We don't bother with this
1556 * for DBs updated to schema 5 because of limitations of the SQLite
1557 * ALTER TABLE command.
1558 */
1559 statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN review_status_id INTEGER NOT NULL DEFAULT " + BlackboardArtifact.ReviewStatus.UNDECIDED.getID());
1560
1561 // Add the encoding table
1562 statement.execute("CREATE TABLE file_encoding_types (encoding_type INTEGER PRIMARY KEY, name TEXT NOT NULL);");
1563 initEncodingTypes(connection);
1564
1565 /*
1566 * This needs to be done due to a Autopsy/TSK out of synch problem.
1567 * Without this, it is possible to upgrade from version 4 to 5 and
1568 * then 5 to 6, but not from 4 to 6.
1569 */
1570 initReviewStatuses(connection);
1571
1572 // Add encoding type column to tsk_files_path
1573 // This should really have the FOREIGN KEY constraint but there are problems
1574 // getting that to work, so we don't add it on this upgrade path.
1575 statement.execute("ALTER TABLE tsk_files_path ADD COLUMN encoding_type INTEGER NOT NULL DEFAULT 0;");
1576
1577 return new CaseDbSchemaVersionNumber(5, 0);
1578
1579 } finally {
1580 closeStatement(statement);
1582 }
1583 }
1584
1598 private CaseDbSchemaVersionNumber updateFromSchema5toSchema6(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1599 if (schemaVersion.getMajor() != 5) {
1600 return schemaVersion;
1601 }
1602
1603 /*
1604 * This upgrade fixes a bug where some releases had artifact review
1605 * status support in the case database and others did not.
1606 */
1607 Statement statement = null;
1608 ResultSet resultSet = null;
1610 try {
1611 /*
1612 * Add the review_statuses lookup table, if missing.
1613 */
1614 statement = connection.createStatement();
1615 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)");
1616
1617 resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM review_statuses"); //NON-NLS
1618 resultSet.next();
1619 if (resultSet.getLong("count") == 0) {
1620 /*
1621 * Add review_status_id column to artifacts table.
1622 *
1623 * NOTE: For DBs created with schema 5 or 6 we define a foreign
1624 * key constraint on the review_status_column. We don't bother
1625 * with this for DBs updated to schema 5 or 6 because of
1626 * limitations of the SQLite ALTER TABLE command.
1627 */
1628 statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN review_status_id INTEGER NOT NULL DEFAULT " + BlackboardArtifact.ReviewStatus.UNDECIDED.getID());
1629 }
1630
1631 return new CaseDbSchemaVersionNumber(6, 0);
1632
1633 } finally {
1634 closeResultSet(resultSet);
1635 closeStatement(statement);
1637 }
1638 }
1639
1653 private CaseDbSchemaVersionNumber updateFromSchema6toSchema7(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1654 if (schemaVersion.getMajor() != 6) {
1655 return schemaVersion;
1656 }
1657
1658 /*
1659 * This upgrade adds an indexed extension column to the tsk_files table.
1660 */
1661 Statement statement = null;
1662 Statement updstatement = null;
1663 ResultSet resultSet = null;
1665 try {
1666 statement = connection.createStatement();
1667 updstatement = connection.createStatement();
1668 statement.execute("ALTER TABLE tsk_files ADD COLUMN extension TEXT");
1669
1670 resultSet = connection.executeQuery(statement, "SELECT obj_id,name FROM tsk_files"); //NON-NLS
1671 while (resultSet.next()) {
1672 long objID = resultSet.getLong("obj_id");
1673 String name = resultSet.getString("name");
1674 updstatement.executeUpdate("UPDATE tsk_files SET extension = '" + escapeSingleQuotes(extractExtension(name)) + "' "
1675 + "WHERE obj_id = " + objID);
1676 }
1677
1678 statement.execute("CREATE INDEX file_extension ON tsk_files ( extension )");
1679
1680 // Add artifact_obj_id column to blackboard_artifacts table, data conversion for old versions isn't necesarry.
1681 statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN artifact_obj_id INTEGER NOT NULL DEFAULT -1");
1682
1683 return new CaseDbSchemaVersionNumber(7, 0);
1684
1685 } finally {
1686 closeResultSet(resultSet);
1687 closeStatement(statement);
1688 closeStatement(updstatement);
1690 }
1691 }
1692
1706 private CaseDbSchemaVersionNumber updateFromSchema7toSchema7dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1707 if (schemaVersion.getMajor() != 7) {
1708 return schemaVersion;
1709 }
1710
1711 if (schemaVersion.getMinor() != 0) {
1712 return schemaVersion;
1713 }
1714
1715 /*
1716 * This upgrade adds a minor version number column.
1717 */
1718 Statement statement = null;
1719 ResultSet resultSet = null;
1721 try {
1722 statement = connection.createStatement();
1723
1724 //add the schema minor version number column.
1725 if (schemaVersion.getMinor() == 0) {
1726 //add the schema minor version number column.
1727 statement.execute("ALTER TABLE tsk_db_info ADD COLUMN schema_minor_ver INTEGER DEFAULT 1");
1728 }
1729 return new CaseDbSchemaVersionNumber(7, 1);
1730
1731 } finally {
1732 closeResultSet(resultSet);
1733 closeStatement(statement);
1735 }
1736 }
1737
1751 private CaseDbSchemaVersionNumber updateFromSchema7dot1toSchema7dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1752 if (schemaVersion.getMajor() != 7) {
1753 return schemaVersion;
1754 }
1755
1756 if (schemaVersion.getMinor() != 1) {
1757 return schemaVersion;
1758 }
1759
1760 Statement statement = null;
1761 Statement updstatement = null;
1762 ResultSet resultSet = null;
1764 try {
1765 //add the data_source_obj_id column to blackboard_artifacts.
1766 statement = connection.createStatement();
1767 statement.execute("ALTER TABLE blackboard_artifacts ADD COLUMN data_source_obj_id INTEGER NOT NULL DEFAULT -1");
1768
1769 // populate data_source_obj_id for each artifact
1770 updstatement = connection.createStatement();
1771 resultSet = connection.executeQuery(statement, "SELECT artifact_id, obj_id FROM blackboard_artifacts"); //NON-NLS
1772 while (resultSet.next()) {
1773 long artifact_id = resultSet.getLong("artifact_id");
1774 long obj_id = resultSet.getLong("obj_id");
1775 long data_source_obj_id = getDataSourceObjectId(connection, obj_id);
1776 updstatement.executeUpdate("UPDATE blackboard_artifacts SET data_source_obj_id = " + data_source_obj_id + " "
1777 + "WHERE artifact_id = " + artifact_id);
1778 }
1779 closeResultSet(resultSet);
1780 closeStatement(statement);
1781 closeStatement(updstatement);
1782
1783 /*
1784 * Add a knownStatus column to the tag_names table.
1785 */
1786 statement = connection.createStatement();
1787 statement.execute("ALTER TABLE tag_names ADD COLUMN knownStatus INTEGER NOT NULL DEFAULT " + TskData.FileKnown.UNKNOWN.getFileKnownValue());
1788
1789 // Create account_types, accounts, and account_relationships table
1790 if (this.dbType.equals(DbType.SQLITE)) {
1791 statement.execute("CREATE TABLE account_types (account_type_id INTEGER PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
1792 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))");
1793 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))");
1794 } else {
1795 statement.execute("CREATE TABLE account_types (account_type_id BIGSERIAL PRIMARY KEY, type_name TEXT UNIQUE NOT NULL, display_name TEXT NOT NULL)");
1796 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))");
1797 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))");
1798 }
1799
1800 // Create indexes
1801 statement.execute("CREATE INDEX artifact_artifact_objID ON blackboard_artifacts(artifact_obj_id)");
1802 statement.execute("CREATE INDEX relationships_account1 ON account_relationships(account1_id)");
1803 statement.execute("CREATE INDEX relationships_account2 ON account_relationships(account2_id)");
1804 statement.execute("CREATE INDEX relationships_relationship_source_obj_id ON account_relationships(relationship_source_obj_id)");
1805 statement.execute("CREATE INDEX relationships_date_time ON account_relationships(date_time)");
1806 statement.execute("CREATE INDEX relationships_relationship_type ON account_relationships(relationship_type)");
1807 statement.execute("CREATE INDEX relationships_data_source_obj_id ON account_relationships(data_source_obj_id)");
1808
1809 return new CaseDbSchemaVersionNumber(7, 2);
1810 } finally {
1811 closeResultSet(resultSet);
1812 closeStatement(statement);
1813 closeStatement(updstatement);
1815 }
1816 }
1817
1831 private CaseDbSchemaVersionNumber updateFromSchema7dot2toSchema8dot0(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1832 if (schemaVersion.getMajor() != 7) {
1833 return schemaVersion;
1834 }
1835
1836 if (schemaVersion.getMinor() != 2) {
1837 return schemaVersion;
1838 }
1839
1840 Statement updateSchemaStatement = connection.createStatement();
1841 Statement getExistingReportsStatement = connection.createStatement();
1842 ResultSet resultSet = null;
1843 ResultSet existingReports = null;
1844
1846 try {
1847 // Update the schema to turn report_id into an object id.
1848
1849 // Unfortunately, SQLite doesn't support adding a constraint
1850 // to an existing table so we have to rename the old...
1851 updateSchemaStatement.execute("ALTER TABLE reports RENAME TO old_reports");
1852
1853 // ...create the new...
1854 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))");
1855
1856 // ...add the existing report records back...
1857 existingReports = getExistingReportsStatement.executeQuery("SELECT * FROM old_reports");
1858 while (existingReports.next()) {
1859 String path = existingReports.getString(2);
1860 long crtime = existingReports.getInt(3);
1861 String sourceModule = existingReports.getString(4);
1862 String reportName = existingReports.getString(5);
1863
1864 PreparedStatement insertObjectStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OBJECT, Statement.RETURN_GENERATED_KEYS);
1865 insertObjectStatement.clearParameters();
1866 insertObjectStatement.setNull(1, java.sql.Types.BIGINT);
1867 insertObjectStatement.setLong(2, TskData.ObjectType.REPORT.getObjectType());
1868 connection.executeUpdate(insertObjectStatement);
1869 resultSet = insertObjectStatement.getGeneratedKeys();
1870 if (!resultSet.next()) {
1871 throw new TskCoreException(String.format("Failed to INSERT report %s (%s) in tsk_objects table", reportName, path));
1872 }
1873 long objectId = resultSet.getLong(1); //last_insert_rowid()
1874
1875 // INSERT INTO reports (obj_id, path, crtime, src_module_name, display_name) VALUES (?, ?, ?, ?, ?)
1876 PreparedStatement insertReportStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_REPORT);
1877 insertReportStatement.clearParameters();
1878 insertReportStatement.setLong(1, objectId);
1879 insertReportStatement.setString(2, path);
1880 insertReportStatement.setLong(3, crtime);
1881 insertReportStatement.setString(4, sourceModule);
1882 insertReportStatement.setString(5, reportName);
1883 connection.executeUpdate(insertReportStatement);
1884 }
1885
1886 // ...and drop the old table.
1887 updateSchemaStatement.execute("DROP TABLE old_reports");
1888
1889 return new CaseDbSchemaVersionNumber(8, 0);
1890 } finally {
1891 closeResultSet(resultSet);
1892 closeResultSet(existingReports);
1893 closeStatement(updateSchemaStatement);
1894 closeStatement(getExistingReportsStatement);
1896 }
1897 }
1898
1912 private CaseDbSchemaVersionNumber updateFromSchema8dot0toSchema8dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1913 if (schemaVersion.getMajor() != 8) {
1914 return schemaVersion;
1915 }
1916
1917 if (schemaVersion.getMinor() != 0) {
1918 return schemaVersion;
1919 }
1920
1922
1923 try (Statement statement = connection.createStatement();) {
1924 // create examiners table
1925 if (this.dbType.equals(DbType.SQLITE)) {
1926 statement.execute("CREATE TABLE tsk_examiners (examiner_id INTEGER PRIMARY KEY, login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name) )");
1927 statement.execute("ALTER TABLE content_tags ADD COLUMN examiner_id INTEGER REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1928 statement.execute("ALTER TABLE blackboard_artifact_tags ADD COLUMN examiner_id INTEGER REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1929 } else {
1930 statement.execute("CREATE TABLE tsk_examiners (examiner_id BIGSERIAL PRIMARY KEY, login_name TEXT NOT NULL, display_name TEXT, UNIQUE(login_name))");
1931 statement.execute("ALTER TABLE content_tags ADD COLUMN examiner_id BIGINT REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1932 statement.execute("ALTER TABLE blackboard_artifact_tags ADD COLUMN examiner_id BIGINT REFERENCES tsk_examiners(examiner_id) DEFAULT NULL");
1933 }
1934
1935 return new CaseDbSchemaVersionNumber(8, 1);
1936 } finally {
1938 }
1939 }
1940
1954 private CaseDbSchemaVersionNumber updateFromSchema8dot1toSchema8dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
1955 if (schemaVersion.getMajor() != 8) {
1956 return schemaVersion;
1957 }
1958
1959 if (schemaVersion.getMinor() != 1) {
1960 return schemaVersion;
1961 }
1962
1964
1965 try (Statement statement = connection.createStatement();) {
1966 statement.execute("ALTER TABLE tsk_image_info ADD COLUMN sha1 TEXT DEFAULT NULL");
1967 statement.execute("ALTER TABLE tsk_image_info ADD COLUMN sha256 TEXT DEFAULT NULL");
1968
1969 statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_details TEXT");
1970
1971 /*
1972 * Add new tsk_db_extended_info table with TSK version, creation
1973 * time schema and schema version numbers as the initial data. The
1974 * creation time schema version is set to 0, 0 to indicate that it
1975 * is not known.
1976 */
1977 statement.execute("CREATE TABLE tsk_db_info_extended (name TEXT PRIMARY KEY, value TEXT NOT NULL)");
1978 ResultSet result = statement.executeQuery("SELECT tsk_ver FROM tsk_db_info");
1979 result.next();
1980 statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + TSK_VERSION_KEY + "', '" + result.getLong("tsk_ver") + "')");
1981 statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + SCHEMA_MAJOR_VERSION_KEY + "', '8')");
1982 statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + SCHEMA_MINOR_VERSION_KEY + "', '2')");
1983 statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + CREATION_SCHEMA_MAJOR_VERSION_KEY + "', '0')");
1984 statement.execute("INSERT INTO tsk_db_info_extended (name, value) VALUES ('" + CREATION_SCHEMA_MINOR_VERSION_KEY + "', '0')");
1985
1986 String primaryKeyType;
1987 switch (getDatabaseType()) {
1988 case POSTGRESQL:
1989 primaryKeyType = "BIGSERIAL";
1990 break;
1991 case SQLITE:
1992 primaryKeyType = "INTEGER";
1993 break;
1994 default:
1995 throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
1996 }
1997
1998 //create and initialize tsk_event_types tables
1999 statement.execute("CREATE TABLE tsk_event_types ("
2000 + " event_type_id " + primaryKeyType + " PRIMARY KEY, "
2001 + " display_name TEXT UNIQUE NOT NULL, "
2002 + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
2003 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2004 + " values( 0, 'Event Types', null)");
2005 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2006 + " values(1, 'File System', 0)");
2007 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2008 + " values(2, 'Web Activity', 0)");
2009 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2010 + " values(3, 'Misc Types', 0)");
2011 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2012 + " values(4, 'Modified', 1)");
2013 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2014 + " values(5, 'Accessed', 1)");
2015 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2016 + " values(6, 'Created', 1)");
2017 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2018 + " values(7, 'Changed', 1)");
2019
2020 //create tsk_events tables
2021 statement.execute("CREATE TABLE tsk_event_descriptions ("
2022 + " event_description_id " + primaryKeyType + " PRIMARY KEY, "
2023 + " full_description TEXT NOT NULL, "
2024 + " med_description TEXT, "
2025 + " short_description TEXT,"
2026 + " data_source_obj_id BIGINT NOT NULL, "
2027 + " file_obj_id BIGINT NOT NULL, "
2028 + " artifact_id BIGINT, "
2029 + " hash_hit INTEGER NOT NULL, " //boolean
2030 + " tagged INTEGER NOT NULL, " //boolean
2031 + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
2032 + " FOREIGN KEY(file_obj_id) REFERENCES tsk_files(obj_id), "
2033 + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
2034 );
2035
2036 statement.execute("CREATE TABLE tsk_events ( "
2037 + " event_id " + primaryKeyType + " PRIMARY KEY, "
2038 + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
2039 + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
2040 + " time INTEGER NOT NULL) "
2041 );
2042
2043 //create tsk_events indices
2044 statement.execute("CREATE INDEX events_time ON tsk_events(time)");
2045 statement.execute("CREATE INDEX events_type ON tsk_events(event_type_id)");
2046 statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2047 statement.execute("CREATE INDEX events_file_obj_id ON tsk_event_descriptions(file_obj_id) ");
2048 statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2049 statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2050 return new CaseDbSchemaVersionNumber(8, 2);
2051
2052 } finally {
2054 }
2055 }
2056
2070 private CaseDbSchemaVersionNumber updateFromSchema8dot2toSchema8dot3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2071 if (schemaVersion.getMajor() != 8) {
2072 return schemaVersion;
2073 }
2074
2075 if (schemaVersion.getMinor() != 2) {
2076 return schemaVersion;
2077 }
2078
2080
2081 ResultSet resultSet = null;
2082
2083 try (Statement statement = connection.createStatement();) {
2084
2085 // Add the uniqueness constraint to the tsk_event and tsk_event_description tables.
2086 // Unfortunately, SQLite doesn't support adding a constraint
2087 // to an existing table so we have to rename the old...
2088 String primaryKeyType;
2089 switch (getDatabaseType()) {
2090 case POSTGRESQL:
2091 primaryKeyType = "BIGSERIAL";
2092 break;
2093 case SQLITE:
2094 primaryKeyType = "INTEGER";
2095 break;
2096 default:
2097 throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
2098 }
2099
2100 //create and initialize tsk_event_types tables which may or may not exist
2101 statement.execute("CREATE TABLE IF NOT EXISTS tsk_event_types ("
2102 + " event_type_id " + primaryKeyType + " PRIMARY KEY, "
2103 + " display_name TEXT UNIQUE NOT NULL, "
2104 + " super_type_id INTEGER REFERENCES tsk_event_types(event_type_id) )");
2105
2106 resultSet = statement.executeQuery("SELECT * from tsk_event_types");
2107
2108 // If there is something in resultSet then the table must have previously
2109 // existing therefore there is not need to populate
2110 if (!resultSet.next()) {
2111
2112 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2113 + " values( 0, 'Event Types', null)");
2114 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2115 + " values(1, 'File System', 0)");
2116 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2117 + " values(2, 'Web Activity', 0)");
2118 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2119 + " values(3, 'Misc Types', 0)");
2120 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2121 + " values(4, 'Modified', 1)");
2122 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2123 + " values(5, 'Accessed', 1)");
2124 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2125 + " values(6, 'Created', 1)");
2126 statement.execute("insert into tsk_event_types(event_type_id, display_name, super_type_id)"
2127 + " values(7, 'Changed', 1)");
2128 }
2129
2130 // Delete the old table that may have been created with the upgrade
2131 // from 8.1 to 8.2.
2132 statement.execute("DROP TABLE IF EXISTS tsk_events");
2133
2134 // Delete the old table that may have been created with the upgrade
2135 // from 8.1 to 8.2
2136 statement.execute("DROP TABLE IF EXISTS tsk_event_descriptions");
2137
2138 //create new tsk_event_description table
2139 statement.execute("CREATE TABLE tsk_event_descriptions ("
2140 + " event_description_id " + primaryKeyType + " PRIMARY KEY, "
2141 + " full_description TEXT NOT NULL, "
2142 + " med_description TEXT, "
2143 + " short_description TEXT,"
2144 + " data_source_obj_id BIGINT NOT NULL, "
2145 + " file_obj_id BIGINT NOT NULL, "
2146 + " artifact_id BIGINT, "
2147 + " hash_hit INTEGER NOT NULL, " //boolean
2148 + " tagged INTEGER NOT NULL, " //boolean
2149 + " UNIQUE(full_description, file_obj_id, artifact_id), "
2150 + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
2151 + " FOREIGN KEY(file_obj_id) REFERENCES tsk_files(obj_id), "
2152 + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
2153 );
2154
2155 // create a new table
2156 statement.execute("CREATE TABLE tsk_events ( "
2157 + " event_id " + primaryKeyType + " PRIMARY KEY, "
2158 + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
2159 + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id) ,"
2160 + " time INTEGER NOT NULL, "
2161 + " UNIQUE (event_type_id, event_description_id, time))"
2162 );
2163
2164 // Fix mistakenly set names in tsk_db_info_extended
2165 statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MAJOR_VERSION' WHERE name = 'CREATED_SCHEMA_MAJOR_VERSION'");
2166 statement.execute("UPDATE tsk_db_info_extended SET name = 'CREATION_SCHEMA_MINOR_VERSION' WHERE name = 'CREATED_SCHEMA_MINOR_VERSION'");
2167
2168 return new CaseDbSchemaVersionNumber(8, 3);
2169 } finally {
2170 closeResultSet(resultSet);
2172 }
2173 }
2174
2196 private CaseDbSchemaVersionNumber updateFromSchema8dot3toSchema8dot4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2197 if (schemaVersion.getMajor() != 8) {
2198 return schemaVersion;
2199 }
2200
2201 if (schemaVersion.getMinor() != 3) {
2202 return schemaVersion;
2203 }
2204
2205 Statement statement = connection.createStatement();
2206 ResultSet results = null;
2207
2209 try {
2210 // This is a bug fix update for a misnamed column in tsk_event_descriptions in
2211 // the previous update code.
2212 if (null == getDatabaseType()) {
2213 throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
2214 }
2215
2216 switch (getDatabaseType()) {
2217 case POSTGRESQL:
2218 // Check if the misnamed column is present
2219 results = statement.executeQuery("SELECT column_name FROM information_schema.columns "
2220 + "WHERE table_name='tsk_event_descriptions' and column_name='file_obj_id'");
2221 if (results.next()) {
2222 // In PostgreSQL we can rename the column if it exists
2223 statement.execute("ALTER TABLE tsk_event_descriptions "
2224 + "RENAME COLUMN file_obj_id TO content_obj_id");
2225
2226 // 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
2227 // Fix the schema, preserving any data if exists.
2228 statement.execute("CREATE TABLE temp_tsk_events ( "
2229 + " event_id BIGSERIAL PRIMARY KEY, "
2230 + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
2231 + " event_description_id BIGINT NOT NULL REFERENCES tsk_event_descriptions(event_description_id),"
2232 + " time BIGINT NOT NULL, "
2233 + " UNIQUE (event_type_id, event_description_id, time))"
2234 );
2235
2236 // Copy the data
2237 statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, "
2238 + "event_description_id, time) SELECT * FROM tsk_events");
2239
2240 // Drop the old table
2241 statement.execute("DROP TABLE tsk_events");
2242
2243 // Rename the new table
2244 statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events");
2245
2246 //create tsk_events indices that were skipped in the 8.2 to 8.3 update code
2247 statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2248 statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) ");
2249 statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2250 statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2251 statement.execute("CREATE INDEX events_time ON tsk_events(time) ");
2252 }
2253 break;
2254 case SQLITE:
2255 boolean hasMisnamedColumn = false;
2256 results = statement.executeQuery("pragma table_info('tsk_event_descriptions')");
2257 while (results.next()) {
2258 if (results.getString("name") != null && results.getString("name").equals("file_obj_id")) {
2259 hasMisnamedColumn = true;
2260 break;
2261 }
2262 }
2263
2264 if (hasMisnamedColumn) {
2265 // Since we can't rename the column we'll need to make new tables and copy the data
2266 statement.execute("CREATE TABLE temp_tsk_event_descriptions ("
2267 + " event_description_id INTEGER PRIMARY KEY, "
2268 + " full_description TEXT NOT NULL, "
2269 + " med_description TEXT, "
2270 + " short_description TEXT,"
2271 + " data_source_obj_id BIGINT NOT NULL, "
2272 + " content_obj_id BIGINT NOT NULL, "
2273 + " artifact_id BIGINT, "
2274 + " hash_hit INTEGER NOT NULL, " //boolean
2275 + " tagged INTEGER NOT NULL, " //boolean
2276 + " UNIQUE(full_description, content_obj_id, artifact_id), "
2277 + " FOREIGN KEY(data_source_obj_id) REFERENCES data_source_info(obj_id), "
2278 + " FOREIGN KEY(content_obj_id) REFERENCES tsk_files(obj_id), "
2279 + " FOREIGN KEY(artifact_id) REFERENCES blackboard_artifacts(artifact_id))"
2280 );
2281
2282 statement.execute("CREATE TABLE temp_tsk_events ( "
2283 + " event_id INTEGER PRIMARY KEY, "
2284 + " event_type_id BIGINT NOT NULL REFERENCES tsk_event_types(event_type_id) ,"
2285 + " event_description_id BIGINT NOT NULL REFERENCES temp_tsk_event_descriptions(event_description_id),"
2286 + " time INTEGER NOT NULL, "
2287 + " UNIQUE (event_type_id, event_description_id, time))"
2288 );
2289
2290 // Copy the data
2291 statement.execute("INSERT INTO temp_tsk_event_descriptions(event_description_id, full_description, "
2292 + "med_description, short_description, data_source_obj_id, content_obj_id, artifact_id, "
2293 + "hash_hit, tagged) SELECT * FROM tsk_event_descriptions");
2294
2295 statement.execute("INSERT INTO temp_tsk_events(event_id, event_type_id, "
2296 + "event_description_id, time) SELECT * FROM tsk_events");
2297
2298 // Drop the old tables
2299 statement.execute("DROP TABLE tsk_events");
2300 statement.execute("DROP TABLE tsk_event_descriptions");
2301
2302 // Rename the new tables
2303 statement.execute("ALTER TABLE temp_tsk_event_descriptions RENAME TO tsk_event_descriptions");
2304 statement.execute("ALTER TABLE temp_tsk_events RENAME TO tsk_events");
2305
2306 //create tsk_events indices
2307 statement.execute("CREATE INDEX events_data_source_obj_id ON tsk_event_descriptions(data_source_obj_id) ");
2308 statement.execute("CREATE INDEX events_content_obj_id ON tsk_event_descriptions(content_obj_id) ");
2309 statement.execute("CREATE INDEX events_artifact_id ON tsk_event_descriptions(artifact_id) ");
2310 statement.execute("CREATE INDEX events_sub_type_time ON tsk_events(event_type_id, time) ");
2311 statement.execute("CREATE INDEX events_time ON tsk_events(time) ");
2312 }
2313 break;
2314 default:
2315 throw new TskCoreException("Unsupported data base type: " + getDatabaseType().toString());
2316 }
2317
2318 // create pool info table
2319 if (this.dbType.equals(DbType.SQLITE)) {
2320 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)");
2321 } else {
2322 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)");
2323 }
2324
2325 // Add new account types for newly supported messaging applications, if they dont exists already.
2326 insertAccountTypeIfNotExists(statement, "IMO", "IMO");
2327 insertAccountTypeIfNotExists(statement, "LINE", "LINE");
2328 insertAccountTypeIfNotExists(statement, "SKYPE", "Skype");
2329 insertAccountTypeIfNotExists(statement, "TANGO", "Tango");
2330 insertAccountTypeIfNotExists(statement, "TEXTNOW", "TextNow");
2331 insertAccountTypeIfNotExists(statement, "THREEMA", "ThreeMa");
2332 insertAccountTypeIfNotExists(statement, "VIBER", "Viber");
2333 insertAccountTypeIfNotExists(statement, "XENDER", "Xender");
2334 insertAccountTypeIfNotExists(statement, "ZAPYA", "Zapya");
2335 insertAccountTypeIfNotExists(statement, "SHAREIT", "ShareIt");
2336
2337 return new CaseDbSchemaVersionNumber(8, 4);
2338 } finally {
2339 closeResultSet(results);
2340 closeStatement(statement);
2342 }
2343 }
2344
2345 private CaseDbSchemaVersionNumber updateFromSchema8dot4toSchema8dot5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2346 if (schemaVersion.getMajor() != 8) {
2347 return schemaVersion;
2348 }
2349
2350 if (schemaVersion.getMinor() != 4) {
2351 return schemaVersion;
2352 }
2353
2354 Statement statement = connection.createStatement();
2356 try {
2357 switch (getDatabaseType()) {
2358 case POSTGRESQL:
2359 statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id BIGSERIAL PRIMARY KEY, name TEXT UNIQUE)");
2360 statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id BIGINT REFERENCES tsk_tag_sets(tag_set_id)");
2361 break;
2362 case SQLITE:
2363 statement.execute("CREATE TABLE tsk_tag_sets (tag_set_id INTEGER PRIMARY KEY, name TEXT UNIQUE)");
2364 statement.execute("ALTER TABLE tag_names ADD COLUMN tag_set_id INTEGER REFERENCES tsk_tag_sets(tag_set_id)");
2365 break;
2366 }
2367
2368 statement.execute("ALTER TABLE tag_names ADD COLUMN rank INTEGER");
2369
2370 /*
2371 * Update existing Project Vic tag names (from Image Gallery in
2372 * Autopsy) to be part of a Tag Set. NOTE: These names are out of
2373 * date and will not work with the Project VIC Report module. New
2374 * cases will get the new names from Image Gallery.
2375 */
2376 String insertStmt = "INSERT INTO tsk_tag_sets (name) VALUES ('Project VIC')";
2377 if (getDatabaseType() == DbType.POSTGRESQL) {
2378 statement.execute(insertStmt, Statement.RETURN_GENERATED_KEYS);
2379 } else {
2380 statement.execute(insertStmt);
2381 }
2382 try (ResultSet resultSet = statement.getGeneratedKeys()) {
2383 if (resultSet != null && resultSet.next()) {
2384 int tagSetId = resultSet.getInt(1);
2385
2386 String updateQuery = "UPDATE tag_names SET tag_set_id = %d, color = '%s', rank = %d, display_name = '%s' WHERE display_name = '%s'";
2387 statement.executeUpdate(String.format(updateQuery, tagSetId, "Red", 1, "Child Exploitation (Illegal)", "CAT-1: Child Exploitation (Illegal)"));
2388 statement.executeUpdate(String.format(updateQuery, tagSetId, "Lime", 2, "Child Exploitation (Non-Illegal/Age Difficult)", "CAT-2: Child Exploitation (Non-Illegal/Age Difficult)"));
2389 statement.executeUpdate(String.format(updateQuery, tagSetId, "Yellow", 3, "CGI/Animation (Child Exploitive)", "CAT-3: CGI/Animation (Child Exploitive)"));
2390 statement.executeUpdate(String.format(updateQuery, tagSetId, "Purple", 4, "Exemplar/Comparison (Internal Use Only)", "CAT-4: Exemplar/Comparison (Internal Use Only)"));
2391 statement.executeUpdate(String.format(updateQuery, tagSetId, "Fuchsia", 5, "Non-pertinent", "CAT-5: Non-pertinent"));
2392
2393 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')";
2394 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')";
2395 String deleteCat0 = "DELETE FROM tag_names WHERE display_name = 'CAT-0: Uncategorized'";
2396 statement.executeUpdate(deleteContentTag);
2397 statement.executeUpdate(deleteArtifactTag);
2398 statement.executeUpdate(deleteCat0);
2399
2400 } else {
2401 throw new TskCoreException("Failed to retrieve the default tag_set_id from DB");
2402 }
2403 }
2404
2405 // Add data_source_obj_id column to the tsk_files table. For newly created cases
2406 // this column will have a foreign key constraint on the data_source_info table.
2407 // There does not seem to be a reasonable way to do this in an upgrade,
2408 // so upgraded cases will be missing the foreign key.
2409 switch (getDatabaseType()) {
2410 case POSTGRESQL:
2411 statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN data_source_obj_id BIGINT NOT NULL DEFAULT -1;");
2412 break;
2413 case SQLITE:
2414 statement.execute("ALTER TABLE tsk_fs_info ADD COLUMN data_source_obj_id INTEGER NOT NULL DEFAULT -1;");
2415 break;
2416 }
2417 Statement updateStatement = connection.createStatement();
2418 try (ResultSet resultSet = statement.executeQuery("SELECT obj_id FROM tsk_fs_info")) {
2419 while (resultSet.next()) {
2420 long fsId = resultSet.getLong("obj_id");
2421 long dataSourceId = getDataSourceObjectId(connection, fsId);
2422 updateStatement.executeUpdate("UPDATE tsk_fs_info SET data_source_obj_id = " + dataSourceId + " WHERE obj_id = " + fsId + ";");
2423 }
2424 } finally {
2425 closeStatement(updateStatement);
2426 }
2427
2428 return new CaseDbSchemaVersionNumber(8, 5);
2429
2430 } finally {
2431 closeStatement(statement);
2433 }
2434 }
2435
2436 private CaseDbSchemaVersionNumber updateFromSchema8dot5toSchema8dot6(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2437 if (schemaVersion.getMajor() != 8) {
2438 return schemaVersion;
2439 }
2440
2441 if (schemaVersion.getMinor() != 5) {
2442 return schemaVersion;
2443 }
2444
2445 Statement statement = connection.createStatement();
2447 try {
2448 statement.execute("ALTER TABLE tsk_files ADD COLUMN sha256 TEXT");
2449
2450 return new CaseDbSchemaVersionNumber(8, 6);
2451
2452 } finally {
2453 closeStatement(statement);
2455 }
2456 }
2457
2458 @SuppressWarnings("deprecation")
2459 private CaseDbSchemaVersionNumber updateFromSchema8dot6toSchema9dot0(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2460 if (schemaVersion.getMajor() != 8) {
2461 return schemaVersion;
2462 }
2463
2464 if (schemaVersion.getMinor() != 6) {
2465 return schemaVersion;
2466 }
2467
2468 Statement statement = connection.createStatement();
2470 try {
2471 String dateDataType = "BIGINT";
2472 String bigIntDataType = "BIGINT";
2473 String blobDataType = "BYTEA";
2474 String primaryKeyType = "BIGSERIAL";
2475
2476 if (this.dbType.equals(DbType.SQLITE)) {
2477 dateDataType = "INTEGER";
2478 bigIntDataType = "INTEGER";
2479 blobDataType = "BLOB";
2480 primaryKeyType = "INTEGER";
2481 }
2482 statement.execute("ALTER TABLE data_source_info ADD COLUMN added_date_time " + dateDataType);
2483 statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_tool_settings TEXT");
2484 statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_tool_name TEXT");
2485 statement.execute("ALTER TABLE data_source_info ADD COLUMN acquisition_tool_version TEXT");
2486
2487 // Add category type and initialize the types. We use the list of artifact types that
2488 // were categorized as analysis results as of the 8.7 update to ensure consistency in
2489 // case the built-in types change in a later release.
2490 statement.execute("ALTER TABLE blackboard_artifact_types ADD COLUMN category_type INTEGER DEFAULT 0");
2491 String analysisTypeObjIdList
2492 = BlackboardArtifact.ARTIFACT_TYPE.TSK_KEYWORD_HIT.getTypeID() + ", "
2493 + BlackboardArtifact.ARTIFACT_TYPE.TSK_HASHSET_HIT.getTypeID() + ", "
2494 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_FILE_HIT.getTypeID() + ", "
2495 + BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_FILE.getTypeID() + ", "
2496 + BlackboardArtifact.ARTIFACT_TYPE.TSK_TAG_ARTIFACT.getTypeID() + ", "
2497 + BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED.getTypeID() + ", "
2498 + BlackboardArtifact.ARTIFACT_TYPE.TSK_EXT_MISMATCH_DETECTED.getTypeID() + ", "
2499 + BlackboardArtifact.ARTIFACT_TYPE.TSK_INTERESTING_ARTIFACT_HIT.getTypeID() + ", "
2500 + BlackboardArtifact.ARTIFACT_TYPE.TSK_FACE_DETECTED.getTypeID() + ", "
2501 + BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED.getTypeID() + ", "
2502 + BlackboardArtifact.ARTIFACT_TYPE.TSK_OBJECT_DETECTED.getTypeID() + ", "
2503 + BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED.getTypeID() + ", "
2504 + BlackboardArtifact.ARTIFACT_TYPE.TSK_DATA_SOURCE_USAGE.getTypeID() + ", "
2505 + BlackboardArtifact.ARTIFACT_TYPE.TSK_USER_CONTENT_SUSPECTED.getTypeID() + ", "
2506 + BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_ACCOUNT_TYPE.getTypeID() + ", "
2507 + BlackboardArtifact.ARTIFACT_TYPE.TSK_YARA_HIT.getTypeID() + ", "
2508 + BlackboardArtifact.ARTIFACT_TYPE.TSK_WEB_CATEGORIZATION.getTypeID();
2509 statement.execute("UPDATE blackboard_artifact_types SET category_type = " + BlackboardArtifact.Category.ANALYSIS_RESULT.getID()
2510 + " WHERE artifact_type_id IN (" + analysisTypeObjIdList + ")");
2511
2512 // Create tsk file attributes table
2513 statement.execute("CREATE TABLE tsk_file_attributes (id " + primaryKeyType + " PRIMARY KEY, "
2514 + "obj_id " + bigIntDataType + " NOT NULL, "
2515 + "attribute_type_id " + bigIntDataType + " NOT NULL, "
2516 + "value_type INTEGER NOT NULL, value_byte " + blobDataType + ", "
2517 + "value_text TEXT, value_int32 INTEGER, value_int64 " + bigIntDataType + ", value_double NUMERIC(20, 10), "
2518 + "FOREIGN KEY(obj_id) REFERENCES tsk_files(obj_id) ON DELETE CASCADE, "
2519 + "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
2520
2521 // create analysis results tables
2522 statement.execute("CREATE TABLE tsk_analysis_results (artifact_obj_id " + bigIntDataType + " PRIMARY KEY, "
2523 + "conclusion TEXT, "
2524 + "significance INTEGER NOT NULL, "
2525 /*
2526 * method_category was a column in a little distributed
2527 * version of 9.0. It was renamed to priority before public
2528 * release. The 9.1 upgrade code will add the priority
2529 * column. This is commented out since it was never used.
2530 */
2531 // + "method_category INTEGER NOT NULL, "
2532 + "configuration TEXT, justification TEXT, "
2533 + "ignore_score INTEGER DEFAULT 0 " // boolean
2534 + ")");
2535
2536 statement.execute("CREATE TABLE tsk_aggregate_score( obj_id " + bigIntDataType + " PRIMARY KEY, "
2537 + "data_source_obj_id " + bigIntDataType + ", "
2538 + "significance INTEGER NOT NULL, "
2539 // See comment above on why this is commented out
2540 // + "method_category INTEGER NOT NULL, "
2541 + "UNIQUE (obj_id),"
2542 + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
2543 + "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE "
2544 + ")");
2545
2546 // Create person table.
2547 statement.execute("CREATE TABLE tsk_persons (id " + primaryKeyType + " PRIMARY KEY, "
2548 + "name TEXT NOT NULL, " // person name
2549 + "UNIQUE(name)) ");
2550
2551 // Create host table.
2552 statement.execute("CREATE TABLE tsk_hosts (id " + primaryKeyType + " PRIMARY KEY, "
2553 + "name TEXT NOT NULL, " // host name
2554 + "db_status INTEGER DEFAULT 0, " // active/merged/deleted
2555 + "person_id INTEGER, "
2556 + "merged_into " + bigIntDataType + ", "
2557 + "FOREIGN KEY(person_id) REFERENCES tsk_persons(id) ON DELETE SET NULL, "
2558 + "FOREIGN KEY(merged_into) REFERENCES tsk_hosts(id), "
2559 + "UNIQUE(name)) ");
2560
2561 // Create OS Account and related tables
2562 statement.execute("CREATE TABLE tsk_os_account_realms (id " + primaryKeyType + " PRIMARY KEY, "
2563 + "realm_name TEXT DEFAULT NULL, " // realm name - for a domain realm, may be null
2564 + "realm_addr TEXT DEFAULT NULL, " // a sid/uid or some some other identifier, may be null
2565 + "realm_signature TEXT NOT NULL, " // Signature exists only to prevent duplicates. It is made up of realm address/name and scope host
2566 + "scope_host_id " + bigIntDataType + " DEFAULT NULL, " // if the realm scope is a single host
2567 + "scope_confidence INTEGER, " // indicates whether we know for sure the realm scope or if we are inferring it
2568 + "db_status INTEGER DEFAULT 0, " // active/merged/deleted
2569 + "merged_into " + bigIntDataType + " DEFAULT NULL, "
2570 + "UNIQUE(realm_signature), "
2571 + "FOREIGN KEY(scope_host_id) REFERENCES tsk_hosts(id),"
2572 + "FOREIGN KEY(merged_into) REFERENCES tsk_os_account_realms(id) )");
2573
2574 // Add host column and create a host for each existing data source.
2575 // We will create a host for each device id so that related data sources will
2576 // be associated with the same host.
2577 statement.execute("ALTER TABLE data_source_info ADD COLUMN host_id INTEGER REFERENCES tsk_hosts(id)");
2578 Statement updateStatement = connection.createStatement();
2579 try (ResultSet resultSet = statement.executeQuery("SELECT obj_id, device_id FROM data_source_info")) {
2580 Map<String, Long> hostMap = new HashMap<>();
2581 long hostIndex = 1;
2582 while (resultSet.next()) {
2583 long objId = resultSet.getLong("obj_id");
2584 String deviceId = resultSet.getString("device_id");
2585
2586 if (!hostMap.containsKey(deviceId)) {
2587 String hostName = "Host " + hostIndex;
2588 updateStatement.execute("INSERT INTO tsk_hosts (name, db_status) VALUES ('" + hostName + "', 0)");
2589 hostMap.put(deviceId, hostIndex);
2590 hostIndex++;
2591 }
2592 updateStatement.execute("UPDATE data_source_info SET host_id = " + hostMap.get(deviceId) + " WHERE obj_id = " + objId);
2593 }
2594 } finally {
2595 closeStatement(updateStatement);
2596 }
2597
2598 statement.execute("CREATE TABLE tsk_os_accounts (os_account_obj_id " + bigIntDataType + " PRIMARY KEY, "
2599 + "login_name TEXT DEFAULT NULL, " // login name, if available, may be null
2600 + "full_name TEXT DEFAULT NULL, " // full name, if available, may be null
2601 + "realm_id " + bigIntDataType + " NOT NULL, " // realm for the account
2602 + "addr TEXT DEFAULT NULL, " // SID/UID, if available
2603 + "signature TEXT NOT NULL, " // This exists only to prevent duplicates. It is either the addr or the login_name whichever is not null.
2604 + "status INTEGER, " // enabled/disabled/deleted
2605 + "type INTEGER, " // service/interactive
2606 + "created_date " + bigIntDataType + " DEFAULT NULL, "
2607 + "db_status INTEGER DEFAULT 0, " // active/merged/deleted
2608 + "merged_into " + bigIntDataType + " DEFAULT NULL, "
2609 + "UNIQUE(signature, realm_id), "
2610 + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
2611 + "FOREIGN KEY(realm_id) REFERENCES tsk_os_account_realms(id),"
2612 + "FOREIGN KEY(merged_into) REFERENCES tsk_os_accounts(os_account_obj_id) )");
2613
2614 statement.execute("CREATE TABLE tsk_os_account_attributes (id " + primaryKeyType + " PRIMARY KEY, "
2615 + "os_account_obj_id " + bigIntDataType + " NOT NULL, "
2616 + "host_id " + bigIntDataType + ", "
2617 + "source_obj_id " + bigIntDataType + ", "
2618 + "attribute_type_id " + bigIntDataType + " NOT NULL, "
2619 + "value_type INTEGER NOT NULL, "
2620 + "value_byte " + bigIntDataType + ", "
2621 + "value_text TEXT, "
2622 + "value_int32 INTEGER, value_int64 " + bigIntDataType + ", "
2623 + "value_double NUMERIC(20, 10), "
2624 + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id), "
2625 + "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id), "
2626 + "FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL, "
2627 + "FOREIGN KEY(attribute_type_id) REFERENCES blackboard_attribute_types(attribute_type_id))");
2628
2629 statement.execute("CREATE TABLE tsk_os_account_instances (id " + primaryKeyType + " PRIMARY KEY, "
2630 + "os_account_obj_id " + bigIntDataType + " NOT NULL, "
2631 + "data_source_obj_id " + bigIntDataType + " NOT NULL, "
2632 + "instance_type INTEGER NOT NULL, " // PerformedActionOn/ReferencedOn
2633 + "UNIQUE(os_account_obj_id, data_source_obj_id), "
2634 + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id), "
2635 + "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE )");
2636
2637 statement.execute("CREATE TABLE tsk_data_artifacts ( "
2638 + "artifact_obj_id " + bigIntDataType + " PRIMARY KEY, "
2639 + "os_account_obj_id " + bigIntDataType + ", "
2640 + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id)) ");
2641
2642 // add owner_uid & os_account_obj_id columns to tsk_files
2643 statement.execute("ALTER TABLE tsk_files ADD COLUMN owner_uid TEXT DEFAULT NULL");
2644 statement.execute("ALTER TABLE tsk_files ADD COLUMN os_account_obj_id " + bigIntDataType + " DEFAULT NULL REFERENCES tsk_os_accounts(os_account_obj_id) ");
2645
2646 // create host address tables
2647 statement.execute("CREATE TABLE tsk_host_addresses (id " + primaryKeyType + " PRIMARY KEY, "
2648 + "address_type INTEGER NOT NULL, "
2649 + "address TEXT NOT NULL, "
2650 + "UNIQUE(address_type, address)) ");
2651
2652 statement.execute("CREATE TABLE tsk_host_address_map (id " + primaryKeyType + " PRIMARY KEY, "
2653 + "host_id " + bigIntDataType + " NOT NULL, "
2654 + "addr_obj_id " + bigIntDataType + " NOT NULL, "
2655 + "source_obj_id " + bigIntDataType + ", " // object id of the source where this mapping was found.
2656 + "time " + bigIntDataType + ", " // time at which the mapping existed
2657 + "UNIQUE(host_id, addr_obj_id, time), "
2658 + "FOREIGN KEY(host_id) REFERENCES tsk_hosts(id) ON DELETE CASCADE, "
2659 + "FOREIGN KEY(addr_obj_id) REFERENCES tsk_host_addresses(id), "
2660 + "FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL )");
2661
2662 // stores associations between DNS name and IP address
2663 statement.execute("CREATE TABLE tsk_host_address_dns_ip_map (id " + primaryKeyType + " PRIMARY KEY, "
2664 + "dns_address_id " + bigIntDataType + " NOT NULL, "
2665 + "ip_address_id " + bigIntDataType + " NOT NULL, "
2666 + "source_obj_id " + bigIntDataType + ", "
2667 + "time " + bigIntDataType + ", " // time at which the mapping existed
2668 + "UNIQUE(dns_address_id, ip_address_id, time), "
2669 + "FOREIGN KEY(dns_address_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE, "
2670 + "FOREIGN KEY(ip_address_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE,"
2671 + "FOREIGN KEY(source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE SET NULL )");
2672
2673 // maps an address to an artifact using it
2674 statement.execute("CREATE TABLE tsk_host_address_usage (id " + primaryKeyType + " PRIMARY KEY, "
2675 + "addr_obj_id " + bigIntDataType + " NOT NULL, "
2676 + "obj_id " + bigIntDataType + " NOT NULL, "
2677 + "data_source_obj_id " + bigIntDataType + " NOT NULL, " // data source where the usage was found
2678 + "UNIQUE(addr_obj_id, obj_id), "
2679 + "FOREIGN KEY(addr_obj_id) REFERENCES tsk_host_addresses(id) ON DELETE CASCADE, "
2680 + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE )");
2681
2682 return new CaseDbSchemaVersionNumber(9, 0);
2683
2684 } finally {
2685 closeStatement(statement);
2687 }
2688 }
2689
2690 private CaseDbSchemaVersionNumber updateFromSchema9dot0toSchema9dot1(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2691 if (schemaVersion.getMajor() != 9) {
2692 return schemaVersion;
2693 }
2694
2695 if (schemaVersion.getMinor() != 0) {
2696 return schemaVersion;
2697 }
2698
2699 Statement statement = connection.createStatement();
2700 ResultSet results = null;
2702 try {
2703 // The 9.0 schema contained method_category columns that were renamed to priority.
2704 switch (getDatabaseType()) {
2705 case POSTGRESQL:
2706 // Check if the misnamed column is present. We'll assume here that the column will exist
2707 // in both tables if present in one.
2708 results = statement.executeQuery("SELECT column_name FROM information_schema.columns "
2709 + "WHERE table_name='tsk_analysis_results' and column_name='method_category'");
2710 if (results.next()) {
2711 // In PostgreSQL we can delete the column
2712 statement.execute("ALTER TABLE tsk_analysis_results "
2713 + "DROP COLUMN method_category");
2714 statement.execute("ALTER TABLE tsk_aggregate_score "
2715 + "DROP COLUMN method_category");
2716 }
2717 break;
2718 case SQLITE:
2719 // Check if the misnamed column is present. We'll assume here that the column will exist
2720 // in both tables if present in one.
2721 boolean hasMisnamedColumn = false;
2722 results = statement.executeQuery("pragma table_info('tsk_analysis_results')");
2723 while (results.next()) {
2724 if (results.getString("name") != null && results.getString("name").equals("method_category")) {
2725 hasMisnamedColumn = true;
2726 break;
2727 }
2728 }
2729
2730 if (hasMisnamedColumn) {
2731 // Since we can't rename the column we'll need to make a new table and copy the data.
2732 // We'll add the priority column later.
2733 statement.execute("CREATE TABLE temp_tsk_analysis_results (artifact_obj_id INTEGER PRIMARY KEY, "
2734 + "conclusion TEXT, "
2735 + "significance INTEGER NOT NULL, "
2736 + "configuration TEXT, justification TEXT, "
2737 + "ignore_score INTEGER DEFAULT 0 " // boolean
2738 + ")");
2739 statement.execute("CREATE TABLE temp_tsk_aggregate_score( obj_id INTEGER PRIMARY KEY, "
2740 + "data_source_obj_id INTEGER, "
2741 + "significance INTEGER NOT NULL, "
2742 + "UNIQUE (obj_id),"
2743 + "FOREIGN KEY(obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE, "
2744 + "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE "
2745 + ")");
2746
2747 // Copy the data
2748 statement.execute("INSERT INTO temp_tsk_analysis_results(artifact_obj_id, "
2749 + "conclusion, justification, significance, configuration, ignore_score) "
2750 + "SELECT artifact_obj_id, conclusion, justification, significance, configuration, ignore_score FROM tsk_analysis_results");
2751 statement.execute("INSERT INTO temp_tsk_aggregate_score(obj_id, "
2752 + "data_source_obj_id, significance) "
2753 + "SELECT obj_id, data_source_obj_id, significance FROM tsk_aggregate_score");
2754
2755 // Drop the old tables
2756 statement.execute("DROP TABLE tsk_analysis_results");
2757 statement.execute("DROP TABLE tsk_aggregate_score");
2758
2759 // Rename the new tables
2760 statement.execute("ALTER TABLE temp_tsk_analysis_results RENAME TO tsk_analysis_results");
2761 statement.execute("ALTER TABLE temp_tsk_aggregate_score RENAME TO tsk_aggregate_score");
2762
2763 }
2764 break;
2765 default:
2766 throw new TskCoreException("Unsupported database type: " + getDatabaseType().toString());
2767 }
2768
2769 // add an index on tsk_file_attributes table.
2770 statement.execute("CREATE INDEX tsk_file_attributes_obj_id ON tsk_file_attributes(obj_id)");
2771
2772 statement.execute("ALTER TABLE tsk_analysis_results ADD COLUMN priority INTEGER NOT NULL DEFAULT " + Score.Priority.NORMAL.getId());
2773 statement.execute("ALTER TABLE tsk_aggregate_score ADD COLUMN priority INTEGER NOT NULL DEFAULT " + Score.Priority.NORMAL.getId());
2774
2775 statement.execute("UPDATE blackboard_artifact_types SET category_type = 1 WHERE artifact_type_id = 16");
2776
2777 return new CaseDbSchemaVersionNumber(9, 1);
2778 } finally {
2779 closeResultSet(results);
2780 closeStatement(statement);
2782 }
2783 }
2784
2798 private CaseDbSchemaVersionNumber updateFromSchema9dot1toSchema9dot2(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2799 if (schemaVersion.getMajor() != 9) {
2800 return schemaVersion;
2801 }
2802
2803 if (schemaVersion.getMinor() != 1) {
2804 return schemaVersion;
2805 }
2806
2807 Statement updateSchemaStatement = connection.createStatement();
2808 ResultSet results = null;
2810 try {
2811
2812 String bigIntDataType = "BIGINT";
2813 String primaryKeyType = "BIGSERIAL";
2814
2815 if (this.dbType.equals(DbType.SQLITE)) {
2816 bigIntDataType = "INTEGER";
2817 primaryKeyType = "INTEGER";
2818 }
2819
2820 // In 9.2 we modified the UNIQUE constraint on tsk_os_account_instances to include instance_type column.
2821 // Since SQLite does not allow to drop or alter constraints, we will create a new table, copy the data and delete the old table.
2822 // Rename existing table
2823 updateSchemaStatement.execute("ALTER TABLE tsk_os_account_instances RENAME TO old_tsk_os_account_instances");
2824
2825 // New table
2826 updateSchemaStatement.execute("CREATE TABLE tsk_os_account_instances (id " + primaryKeyType + " PRIMARY KEY, "
2827 + "os_account_obj_id " + bigIntDataType + " NOT NULL, "
2828 + "data_source_obj_id " + bigIntDataType + " NOT NULL, "
2829 + "instance_type INTEGER NOT NULL, " // PerformedActionOn/ReferencedOn
2830 + "UNIQUE(os_account_obj_id, data_source_obj_id, instance_type), "
2831 + "FOREIGN KEY(os_account_obj_id) REFERENCES tsk_os_accounts(os_account_obj_id) ON DELETE CASCADE, "
2832 + "FOREIGN KEY(data_source_obj_id) REFERENCES tsk_objects(obj_id) ON DELETE CASCADE ) ");
2833
2834 // Copy the data from old table, order by id preserves the primary key.
2835 updateSchemaStatement.execute("INSERT INTO tsk_os_account_instances(os_account_obj_id, "
2836 + "data_source_obj_id, instance_type) SELECT os_account_obj_id, data_source_obj_id, instance_type FROM old_tsk_os_account_instances ORDER BY id ASC");
2837
2838 // delete old table
2839 updateSchemaStatement.execute("DROP TABLE old_tsk_os_account_instances");
2840
2841 return new CaseDbSchemaVersionNumber(9, 2);
2842 } finally {
2843 closeResultSet(results);
2844 closeStatement(updateSchemaStatement);
2846 }
2847 }
2848
2849 private CaseDbSchemaVersionNumber updateFromSchema9dot2toSchema9dot3(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2850 if (schemaVersion.getMajor() != 9) {
2851 return schemaVersion;
2852 }
2853
2854 if (schemaVersion.getMinor() != 2) {
2855 return schemaVersion;
2856 }
2857
2858 Statement statement = connection.createStatement();
2860 try {
2861 // add a new column 'sha1' to tsk_files
2862 statement.execute("ALTER TABLE tsk_files ADD COLUMN sha1 TEXT");
2863
2864
2865 return new CaseDbSchemaVersionNumber(9, 3);
2866
2867 } finally {
2868 closeStatement(statement);
2870 }
2871 }
2872
2873 private CaseDbSchemaVersionNumber updateFromSchema9dot3toSchema9dot4(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2874 if (schemaVersion.getMajor() != 9) {
2875 return schemaVersion;
2876 }
2877
2878 if (schemaVersion.getMinor() != 3) {
2879 return schemaVersion;
2880 }
2881
2882 Statement statement = connection.createStatement();
2884 try {
2885 // Add file_collection_status_types table
2886 statement.execute("CREATE TABLE file_collection_status_types (collection_status_type INTEGER PRIMARY KEY, name TEXT NOT NULL);");
2887 initCollectedStatusTypes(connection);
2888
2889 // add a new column 'collected' to tsk_files
2890 statement.execute("ALTER TABLE tsk_files ADD COLUMN collected INTEGER NOT NULL DEFAULT " +
2891 TskData.CollectedStatus.UNKNOWN.getType() + ";");
2892
2893 return new CaseDbSchemaVersionNumber(9, 4);
2894
2895 } finally {
2896 closeStatement(statement);
2898 }
2899 }
2900
2901 private CaseDbSchemaVersionNumber updateFromSchema9dot4toSchema9dot5(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2902 if (schemaVersion.getMajor() != 9) {
2903 return schemaVersion;
2904 }
2905
2906 if (schemaVersion.getMinor() != 4) {
2907 return schemaVersion;
2908 }
2909
2910 Statement statement = connection.createStatement();
2912 try {
2913 // Adding indexes to the os account table
2914 statement.execute("CREATE INDEX tsk_os_accounts_login_name_idx ON tsk_os_accounts(login_name, db_status, realm_id)");
2915 statement.execute("CREATE INDEX tsk_os_accounts_addr_idx ON tsk_os_accounts(addr, db_status, realm_id)");
2916 statement.execute("CREATE INDEX tsk_os_account_realms_realm_name_idx ON tsk_os_account_realms(realm_name)");
2917 statement.execute("CREATE INDEX tsk_os_account_realms_realm_addr_idx ON tsk_os_account_realms(realm_addr)");
2918
2919 return new CaseDbSchemaVersionNumber(9, 5);
2920
2921 } finally {
2922 closeStatement(statement);
2924 }
2925 }
2926
2927 private CaseDbSchemaVersionNumber updateFromSchema9dot5toSchema9dot6(CaseDbSchemaVersionNumber schemaVersion, CaseDbConnection connection) throws SQLException, TskCoreException {
2928 if (schemaVersion.getMajor() != 9) {
2929 return schemaVersion;
2930 }
2931
2932 if (schemaVersion.getMinor() != 5) {
2933 return schemaVersion;
2934 }
2935
2936 String insertSQL = "";
2937 switch (getDatabaseType()) {
2938 case POSTGRESQL:
2939 insertSQL = "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"; //NON-NLS
2940 break;
2941 case SQLITE:
2942 insertSQL = "CREATE INDEX tsk_files_datasrc_md5_size_index ON tsk_files(data_source_obj_id, md5, size)";
2943 break;
2944 default:
2945 throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
2946 }
2947
2948 Statement statement = connection.createStatement();
2950 try {
2951 // Adding index to the tsk_files table
2952 statement.execute(insertSQL);
2953
2954 return new CaseDbSchemaVersionNumber(9, 6);
2955
2956 } finally {
2957 closeStatement(statement);
2959 }
2960 }
2961
2973 private void insertAccountTypeIfNotExists(Statement statement, String type_name, String display_name) throws TskCoreException, SQLException {
2974
2975 String insertSQL = String.format("INTO account_types(type_name, display_name) VALUES ('%s', '%s')", type_name, display_name);
2976 switch (getDatabaseType()) {
2977 case POSTGRESQL:
2978 insertSQL = "INSERT " + insertSQL + " ON CONFLICT DO NOTHING"; //NON-NLS
2979 break;
2980 case SQLITE:
2981 insertSQL = "INSERT OR IGNORE " + insertSQL;
2982 break;
2983 default:
2984 throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
2985 }
2986 statement.execute(insertSQL); //NON-NLS
2987 }
2988
2996 static String extractExtension(final String fileName) {
2997 String ext;
2998 int i = fileName.lastIndexOf(".");
2999 // > 0 because we assume it's not an extension if period is the first character
3000 if ((i > 0) && ((i + 1) < fileName.length())) {
3001 ext = fileName.substring(i + 1);
3002 } else {
3003 return "";
3004 }
3005 // we added this at one point to deal with files that had crazy names based on URLs
3006 // it's too hard though to clean those up and not mess up basic extensions though.
3007 // We need to add '-' to the below if we use it again
3008 // String[] findNonAlphanumeric = ext.split("[^a-zA-Z0-9_]");
3009 // if (findNonAlphanumeric.length > 1) {
3010 // ext = findNonAlphanumeric[0];
3011 // }
3012 return ext.toLowerCase();
3013 }
3014
3025 @Deprecated
3026 public int getSchemaVersion() {
3027 return getDBSchemaVersion().getMajor();
3028 }
3029
3036 return CURRENT_DB_SCHEMA_VERSION;
3037 }
3038
3046 return caseDBSchemaCreationVersion;
3047 }
3048
3055 return this.dbType;
3056 }
3057
3064 public String getBackupDatabasePath() {
3065 return dbBackupPath;
3066 }
3067
3083 return new CaseDbTransaction(this, false);
3084 }
3085
3104 @Beta
3106 return new CaseDbTransaction(this, true);
3107 }
3108
3109
3115 public String getDatabaseName() {
3116 return databaseName;
3117 }
3118
3125 public String getDbDirPath() {
3126 return caseDirPath;
3127 }
3128
3135 if (dbType == DbType.SQLITE) {
3136 rwLock.writeLock().lock();
3137 }
3138 }
3139
3146 if (dbType == DbType.SQLITE) {
3147 rwLock.writeLock().unlock();
3148 }
3149 }
3150
3157 if (dbType == DbType.SQLITE) {
3158 rwLock.readLock().lock();
3159 }
3160 }
3161
3168 if (dbType == DbType.SQLITE) {
3169 rwLock.readLock().unlock();
3170 }
3171 }
3172
3182 public static SleuthkitCase openCase(String dbPath) throws TskCoreException {
3183 return openCase(dbPath, null);
3184 }
3185
3196 @Beta
3197 public static SleuthkitCase openCase(String dbPath, ContentStreamProvider contentProvider) throws TskCoreException {
3198 return openCase(dbPath, contentProvider, null);
3199 }
3200
3213 @Beta
3214 public static SleuthkitCase openCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName) throws TskCoreException {
3215 return openCase(dbPath, contentProvider, null, false);
3216 }
3217
3234 @Beta
3235 public static SleuthkitCase openCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName, boolean useWAL) throws TskCoreException {
3236 try {
3237 final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath);
3238 return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE, contentProvider, lockingApplicationName, useWAL);
3240 //don't wrap in new TskCoreException
3241 throw ex;
3242 } catch (Exception ex) {
3243 throw new TskCoreException("Failed to open case database at " + dbPath, ex);
3244 }
3245 }
3246
3247
3248
3249
3261 public static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir) throws TskCoreException {
3262 return openCase(databaseName, info, caseDir, null);
3263 }
3264
3277 @Beta
3278 public static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir, ContentStreamProvider contentProvider) throws TskCoreException {
3279 try {
3280 /*
3281 * The flow of this method involves trying to open case and if
3282 * successful, return that case. If unsuccessful, an exception is
3283 * thrown. We catch any exceptions, and use tryConnect() to attempt
3284 * to obtain further information about the error. If tryConnect() is
3285 * unable to successfully connect, tryConnect() will throw a
3286 * TskCoreException with a message containing user-level error
3287 * reporting. If tryConnect() is able to connect, flow continues and
3288 * we rethrow the original exception obtained from trying to create
3289 * the case. In this way, we obtain more detailed information if we
3290 * are able, but do not lose any information if unable.
3291 */
3292 final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info);
3293 return new SleuthkitCase(info, databaseName, caseHandle, caseDir, contentProvider);
3294 } catch (PropertyVetoException exp) {
3295 // In this case, the JDBC driver doesn't support PostgreSQL. Use the generic message here.
3296 throw new TskCoreException(exp.getMessage(), exp);
3298 //don't wrap in new TskCoreException
3299 throw ex;
3300 } catch (Exception exp) {
3301 tryConnect(info); // attempt to connect, throw with user-friendly message if unable
3302 throw new TskCoreException(exp.getMessage(), exp); // throw with generic message if tryConnect() was successful
3303 }
3304 }
3305
3315 public static SleuthkitCase newCase(String dbPath) throws TskCoreException {
3316 return newCase(dbPath, null);
3317 }
3318
3329 @Beta
3330 public static SleuthkitCase newCase(String dbPath, ContentStreamProvider contentProvider) throws TskCoreException {
3331 return newCase(dbPath, contentProvider, null);
3332 }
3333
3349 @Beta
3350 public static SleuthkitCase newCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName) throws TskCoreException {
3351 return newCase(dbPath, contentProvider, null, false);
3352 }
3353
3373 @Beta
3374 public static SleuthkitCase newCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName, boolean useWAL) throws TskCoreException {
3375
3376 try {
3377 CaseDatabaseFactory factory = new CaseDatabaseFactory(dbPath);
3378 factory.createCaseDatabase();
3379
3380 SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(dbPath);
3381 return new SleuthkitCase(dbPath, caseHandle, DbType.SQLITE, contentProvider, lockingApplicationName, useWAL);
3382 } catch (Exception ex) {
3383 throw new TskCoreException("Failed to create case database at " + dbPath, ex);
3384 }
3385 }
3386
3402 public static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath) throws TskCoreException {
3403 return newCase(caseName, info, caseDirPath, null);
3404 }
3405
3406
3423 @Beta
3424 public static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath, ContentStreamProvider contentProvider) throws TskCoreException {
3425 String databaseName = createCaseDataBaseName(caseName);
3426 try {
3439 CaseDatabaseFactory factory = new CaseDatabaseFactory(databaseName, info);
3440 factory.createCaseDatabase();
3441
3442 final SleuthkitJNI.CaseDbHandle caseHandle = SleuthkitJNI.openCaseDb(databaseName, info);
3443 return new SleuthkitCase(info, databaseName, caseHandle, caseDirPath, contentProvider);
3444 } catch (PropertyVetoException exp) {
3445 // In this case, the JDBC driver doesn't support PostgreSQL. Use the generic message here.
3446 throw new TskCoreException(exp.getMessage(), exp);
3447 } catch (Exception exp) {
3448 tryConnect(info); // attempt to connect, throw with user-friendly message if unable
3449 throw new TskCoreException(exp.getMessage(), exp); // throw with generic message if tryConnect() was successful
3450 }
3451 }
3452
3462 private static String createCaseDataBaseName(String candidateDbName) {
3463 String dbName;
3464 if (!candidateDbName.isEmpty()) {
3465 /*
3466 * Replace all non-ASCII characters.
3467 */
3468 dbName = candidateDbName.replaceAll("[^\\p{ASCII}]", "_"); //NON-NLS
3469
3470 /*
3471 * Replace all control characters.
3472 */
3473 dbName = dbName.replaceAll("[\\p{Cntrl}]", "_"); //NON-NLS
3474
3475 /*
3476 * Replace /, \, :, ?, space, ' ".
3477 */
3478 dbName = dbName.replaceAll("[ /?:'\"\\\\]", "_"); //NON-NLS
3479
3480 /*
3481 * Make it all lowercase.
3482 */
3483 dbName = dbName.toLowerCase();
3484
3485 /*
3486 * Must start with letter or underscore. If not, prepend an
3487 * underscore.
3488 */
3489 if ((dbName.length() > 0 && !(Character.isLetter(dbName.codePointAt(0))) && !(dbName.codePointAt(0) == '_'))) {
3490 dbName = "_" + dbName;
3491 }
3492
3493 /*
3494 * Truncate to 63 - 16 = 47 chars to accomodate a timestamp for
3495 * uniqueness.
3496 */
3497 if (dbName.length() > MAX_DB_NAME_LEN_BEFORE_TIMESTAMP) {
3498 dbName = dbName.substring(0, MAX_DB_NAME_LEN_BEFORE_TIMESTAMP);
3499 }
3500
3501 } else {
3502 /*
3503 * Must start with letter or underscore.
3504 */
3505 dbName = "_";
3506 }
3507 /*
3508 * Add the time stmap.
3509 */
3510 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd_HHmmss");
3511 Date date = new Date();
3512 dbName = dbName + "_" + dateFormat.format(date);
3513
3514 return dbName;
3515 }
3516
3522 @Beta
3524 timelineEventsDisabled.set(true);
3525 }
3526
3535
3536 // return cached value if there's one
3537 if (cachedCurrentExaminer != null) {
3538 return cachedCurrentExaminer;
3539 }
3540 String loginName = System.getProperty("user.name");
3541 if (loginName == null || loginName.isEmpty()) {
3542 throw new TskCoreException("Failed to determine logged in user name.");
3543 }
3544
3545 ResultSet resultSet = null;
3546 CaseDbConnection connection = null;
3548 try {
3549 connection = connections.getConnection();
3550 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_EXAMINER_BY_LOGIN_NAME);
3551 statement.clearParameters();
3552 statement.setString(1, loginName);
3553 resultSet = connection.executeQuery(statement);
3554 if (resultSet.next()) {
3555 cachedCurrentExaminer = new Examiner(resultSet.getLong("examiner_id"), resultSet.getString("login_name"), resultSet.getString("display_name"));
3556 return cachedCurrentExaminer;
3557 } else {
3558 throw new TskCoreException("Error getting examaminer for name = " + loginName);
3559 }
3560
3561 } catch (SQLException ex) {
3562 throw new TskCoreException("Error getting examaminer for name = " + loginName, ex);
3563 } finally {
3564 closeResultSet(resultSet);
3565 closeConnection(connection);
3567 }
3568
3569 }
3570
3580 Examiner getExaminerById(long id) throws TskCoreException {
3581
3582 CaseDbConnection connection = null;
3583 ResultSet resultSet = null;
3585 try {
3586 connection = connections.getConnection();
3587 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_EXAMINER_BY_ID);
3588 statement.clearParameters();
3589 statement.setLong(1, id);
3590 resultSet = connection.executeQuery(statement);
3591 if (resultSet.next()) {
3592 return new Examiner(resultSet.getLong("examiner_id"), resultSet.getString("login_name"), resultSet.getString("full_name"));
3593 } else {
3594 throw new TskCoreException("Error getting examaminer for id = " + id);
3595 }
3596 } catch (SQLException ex) {
3597 throw new TskCoreException("Error getting examaminer for id = " + id, ex);
3598 } finally {
3599 closeResultSet(resultSet);
3600 closeConnection(connection);
3602 }
3603 }
3604
3622 public AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath) {
3623 return makeAddImageProcess(timeZone, addUnallocSpace, noFatFsOrphans, imageCopyPath, null);
3624 }
3625
3645 @Beta
3646 public AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath, String password) {
3647 return this.caseHandle.initAddImageProcess(timeZone, addUnallocSpace, noFatFsOrphans, imageCopyPath, password, this);
3648 }
3649
3658 public List<Content> getRootObjects() throws TskCoreException {
3659 CaseDbConnection connection = null;
3660 Statement s = null;
3661 ResultSet rs = null;
3663 try {
3664 connection = connections.getConnection();
3665 s = connection.createStatement();
3666 rs = connection.executeQuery(s, "SELECT obj_id, type FROM tsk_objects " //NON-NLS
3667 + "WHERE par_obj_id IS NULL"); //NON-NLS
3668 Collection<ObjectInfo> infos = new ArrayList<ObjectInfo>();
3669 while (rs.next()) {
3670 infos.add(new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")))); //NON-NLS
3671 }
3672
3673 List<Content> rootObjs = new ArrayList<Content>();
3674 for (ObjectInfo i : infos) {
3675 if (null != i.type) {
3676 switch (i.type) {
3677 case IMG:
3678 rootObjs.add(getImageById(i.id));
3679 break;
3680 case ABSTRACTFILE:
3681 // Check if virtual dir for local files.
3683 if (af instanceof VirtualDirectory) {
3684 rootObjs.add(af);
3685 } else {
3686 throw new TskCoreException("Parentless object has wrong type to be a root (ABSTRACTFILE, but not VIRTUAL_DIRECTORY: " + i.type);
3687 }
3688 break;
3689 case REPORT:
3690 break;
3691 case OS_ACCOUNT:
3692 break;
3693 case HOST_ADDRESS:
3694 break;
3695 case UNSUPPORTED:
3696 break;
3697 default:
3698 throw new TskCoreException("Parentless object has wrong type to be a root: " + i.type);
3699 }
3700 }
3701 }
3702 return rootObjs;
3703 } catch (SQLException ex) {
3704 throw new TskCoreException("Error getting root objects", ex);
3705 } finally {
3706 closeResultSet(rs);
3707 closeStatement(s);
3708 closeConnection(connection);
3710 }
3711 }
3712
3724 List<Long> getDataSourceObjIds(String deviceId) throws TskCoreException {
3725
3726 // check cached map first
3727 synchronized (deviceIdToDatasourceObjIdMap) {
3728 if (deviceIdToDatasourceObjIdMap.containsKey(deviceId)) {
3729 return new ArrayList<Long>(deviceIdToDatasourceObjIdMap.get(deviceId));
3730 }
3731
3732 CaseDbConnection connection = null;
3733 Statement s = null;
3734 ResultSet rs = null;
3736 try {
3737 connection = connections.getConnection();
3738 s = connection.createStatement();
3739 rs = connection.executeQuery(s, "SELECT obj_id FROM data_source_info WHERE device_id = '" + deviceId + "'"); //NON-NLS
3740 List<Long> dataSourceObjIds = new ArrayList<Long>();
3741 while (rs.next()) {
3742 dataSourceObjIds.add(rs.getLong("obj_id"));
3743
3744 // Add to map of deviceID to data_source_obj_id.
3745 long ds_obj_id = rs.getLong("obj_id");
3746 if (deviceIdToDatasourceObjIdMap.containsKey(deviceId)) {
3747 deviceIdToDatasourceObjIdMap.get(deviceId).add(ds_obj_id);
3748 } else {
3749 deviceIdToDatasourceObjIdMap.put(deviceId, new HashSet<Long>(Arrays.asList(ds_obj_id)));
3750 }
3751 }
3752 return dataSourceObjIds;
3753 } catch (SQLException ex) {
3754 throw new TskCoreException("Error getting data sources", ex);
3755 } finally {
3756 closeResultSet(rs);
3757 closeStatement(s);
3758 closeConnection(connection);
3760 }
3761 }
3762 }
3763
3780 public List<DataSource> getDataSources() throws TskCoreException {
3781 CaseDbConnection connection = null;
3782 Statement statement = null;
3783 ResultSet resultSet = null;
3784 Statement statement2 = null;
3785 ResultSet resultSet2 = null;
3787 try {
3788 connection = connections.getConnection();
3789 statement = connection.createStatement();
3790 statement2 = connection.createStatement();
3791 resultSet = connection.executeQuery(statement,
3792 "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 "
3793 + "FROM data_source_info AS ds "
3794 + "LEFT JOIN tsk_image_info AS img "
3795 + "ON ds.obj_id = img.obj_id"); //NON-NLS
3796
3797 List<DataSource> dataSourceList = new ArrayList<DataSource>();
3798 Map<Long, List<String>> imagePathsMap = getImagePaths();
3799
3800 while (resultSet.next()) {
3801 DataSource dataSource;
3802 Long objectId = resultSet.getLong("obj_id");
3803 String deviceId = resultSet.getString("device_id");
3804 String timezone = resultSet.getString("time_zone");
3805 String type = resultSet.getString("type");
3806
3807 if (type == null) {
3808 /*
3809 * No data found in 'tsk_image_info', so we build a
3810 * LocalFilesDataSource.
3811 */
3812
3813 resultSet2 = connection.executeQuery(statement2, "SELECT name FROM tsk_files WHERE tsk_files.obj_id = " + objectId); //NON-NLS
3814 String dsName = (resultSet2.next()) ? resultSet2.getString("name") : "";
3815 resultSet2.close();
3816
3820 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
3821 | TSK_FS_META_FLAG_ENUM.USED.getValue());
3822 String parentPath = "/"; //NON-NLS
3823 dataSource = new LocalFilesDataSource(this, objectId, objectId, deviceId, dsName, dirType, metaType, dirFlag, metaFlags, timezone, null, null, null, FileKnown.UNKNOWN, parentPath);
3824 } else {
3825 /*
3826 * Data found in 'tsk_image_info', so we build an Image.
3827 */
3828 Long ssize = resultSet.getLong("ssize");
3829 Long size = resultSet.getLong("size");
3830 String md5 = resultSet.getString("md5");
3831 String sha1 = resultSet.getString("sha1");
3832 String sha256 = resultSet.getString("sha256");
3833 String name = resultSet.getString("display_name");
3834
3835 List<String> imagePaths = imagePathsMap.get(objectId);
3836 if (name == null) {
3837 if (imagePaths.size() > 0) {
3838 String path = imagePaths.get(0);
3839 name = (new java.io.File(path)).getName();
3840 } else {
3841 name = "";
3842 }
3843 }
3844
3845 dataSource = new Image(this, objectId, Long.valueOf(type), deviceId, ssize, name,
3846 imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
3847 }
3848
3849 dataSourceList.add(dataSource);
3850 }
3851
3852 return dataSourceList;
3853
3854 } catch (SQLException ex) {
3855 throw new TskCoreException("Error getting data sources", ex);
3856 } finally {
3857 closeResultSet(resultSet);
3858 closeStatement(statement);
3859 closeResultSet(resultSet2);
3860 closeStatement(statement2);
3861 closeConnection(connection);
3863 }
3864 }
3865
3886 DataSource dataSource = null;
3887 CaseDbConnection connection = null;
3888 Statement statement = null;
3889 ResultSet resultSet = null;
3890 Statement statement2 = null;
3891 ResultSet resultSet2 = null;
3893 try {
3894 connection = connections.getConnection();
3895 statement = connection.createStatement();
3896 statement2 = connection.createStatement();
3897 resultSet = connection.executeQuery(statement,
3898 "SELECT ds.device_id, ds.time_zone, img.type, img.ssize, img.size, img.md5, img.sha1, img.sha256, img.display_name "
3899 + "FROM data_source_info AS ds "
3900 + "LEFT JOIN tsk_image_info AS img "
3901 + "ON ds.obj_id = img.obj_id "
3902 + "WHERE ds.obj_id = " + objectId); //NON-NLS
3903 if (resultSet.next()) {
3904 String deviceId = resultSet.getString("device_id");
3905 String timezone = resultSet.getString("time_zone");
3906 String type = resultSet.getString("type");
3907
3908 if (type == null) {
3909 /*
3910 * No data found in 'tsk_image_info', so we build an
3911 * LocalFilesDataSource.
3912 */
3913
3914 resultSet2 = connection.executeQuery(statement2, "SELECT name FROM tsk_files WHERE tsk_files.obj_id = " + objectId); //NON-NLS
3915 String dsName = (resultSet2.next()) ? resultSet2.getString("name") : "";
3916
3920 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
3921 | TSK_FS_META_FLAG_ENUM.USED.getValue());
3922 String parentPath = "/"; //NON-NLS
3923 dataSource = new LocalFilesDataSource(this, objectId, objectId, deviceId, dsName, dirType, metaType, dirFlag, metaFlags, timezone, null, null, null, FileKnown.UNKNOWN, parentPath);
3924 } else {
3925 /*
3926 * Data found in 'tsk_image_info', so we build an Image.
3927 */
3928 Long ssize = resultSet.getLong("ssize");
3929 Long size = resultSet.getLong("size");
3930 String md5 = resultSet.getString("md5");
3931 String sha1 = resultSet.getString("sha1");
3932 String sha256 = resultSet.getString("sha256");
3933 String name = resultSet.getString("display_name");
3934
3935 List<String> imagePaths = getImagePathsById(objectId, connection);
3936 if (name == null) {
3937 if (imagePaths.size() > 0) {
3938 String path = imagePaths.get(0);
3939 name = (new java.io.File(path)).getName();
3940 } else {
3941 name = "";
3942 }
3943 }
3944
3945 dataSource = new Image(this, objectId, Long.valueOf(type), deviceId, ssize, name,
3946 imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, size);
3947 }
3948 } else {
3949 throw new TskDataException(String.format("There is no data source with obj_id = %d", objectId));
3950 }
3951 } catch (SQLException ex) {
3952 throw new TskCoreException(String.format("Error getting data source with obj_id = %d", objectId), ex);
3953 } finally {
3954 closeResultSet(resultSet);
3955 closeStatement(statement);
3956 closeResultSet(resultSet2);
3957 closeStatement(statement2);
3958 closeConnection(connection);
3960 }
3961
3962 return dataSource;
3963 }
3964
3977 @Deprecated
3978 public ArrayList<BlackboardArtifact> getBlackboardArtifacts(int artifactTypeID) throws TskCoreException {
3979 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
3980 artifacts.addAll(blackboard.getArtifactsByType(blackboard.getArtifactType(artifactTypeID)));
3981 return artifacts;
3982 }
3983
3994 public long getBlackboardArtifactsCount(long objId) throws TskCoreException {
3995 CaseDbConnection connection = null;
3996 ResultSet rs = null;
3998 try {
3999 connection = connections.getConnection();
4000
4001 // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ?
4002 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_FROM_SOURCE);
4003 statement.clearParameters();
4004 statement.setLong(1, objId);
4005 rs = connection.executeQuery(statement);
4006 long count = 0;
4007 if (rs.next()) {
4008 count = rs.getLong("count");
4009 }
4010 return count;
4011 } catch (SQLException ex) {
4012 throw new TskCoreException("Error getting number of blackboard artifacts by content", ex);
4013 } finally {
4014 closeResultSet(rs);
4015 closeConnection(connection);
4017 }
4018 }
4019
4030 public long getBlackboardArtifactsTypeCount(int artifactTypeID) throws TskCoreException {
4031 CaseDbConnection connection = null;
4032 ResultSet rs = null;
4034 try {
4035 connection = connections.getConnection();
4036
4037 // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ?
4038 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_OF_TYPE);
4039 statement.clearParameters();
4040 statement.setInt(1, artifactTypeID);
4041 rs = connection.executeQuery(statement);
4042 long count = 0;
4043 if (rs.next()) {
4044 count = rs.getLong("count");
4045 }
4046 return count;
4047 } catch (SQLException ex) {
4048 throw new TskCoreException("Error getting number of blackboard artifacts by type", ex);
4049 } finally {
4050 closeResultSet(rs);
4051 closeConnection(connection);
4053 }
4054 }
4055
4067 public long getBlackboardArtifactsTypeCount(int artifactTypeID, long dataSourceID) throws TskCoreException {
4068 CaseDbConnection connection = null;
4069 ResultSet rs = null;
4071 try {
4072 connection = connections.getConnection();
4073
4074 // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE artifact_type_id = ?
4075 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_OF_TYPE_BY_DATA_SOURCE);
4076 statement.clearParameters();
4077 statement.setInt(2, artifactTypeID);
4078 statement.setLong(1, dataSourceID);
4079 rs = connection.executeQuery(statement);
4080 long count = 0;
4081 if (rs.next()) {
4082 count = rs.getLong("count");
4083 }
4084 return count;
4085 } catch (SQLException ex) {
4086 throw new TskCoreException(String.format("Error getting number of blackboard artifacts by type (%d) and data source (%d)", artifactTypeID, dataSourceID), ex);
4087 } finally {
4088 closeResultSet(rs);
4089 closeConnection(connection);
4091 }
4092 }
4093
4110 @Deprecated
4111 public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value) throws TskCoreException {
4113 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement();
4114 ResultSet resultSet = connection.executeQuery(statement, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4115 + "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, "
4116 + "types.type_name AS type_name, types.display_name AS display_name, "//NON-NLS
4117 + " arts.review_status_id AS review_status_id " //NON-NLS
4118 + "FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
4119 + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4120 + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
4121 + " AND attrs.value_text = '" + value + "'"
4122 + " AND types.artifact_type_id=arts.artifact_type_id"
4123 + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());) { //NON-NLS
4124
4125 List<Long> analysisArtifactObjIds = new ArrayList<>();
4126 List<Long> dataArtifactObjIds = new ArrayList<>();
4127 while (resultSet.next()) {
4128 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
4129 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
4130 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4131 } else {
4132 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4133 }
4134 }
4135
4136 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4137 if (!analysisArtifactObjIds.isEmpty()) {
4138 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
4139 }
4140
4141 if (!dataArtifactObjIds.isEmpty()) {
4142 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
4143 }
4144 return artifacts;
4145 } catch (SQLException ex) {
4146 throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
4147 } finally {
4149 }
4150 }
4151
4170 @Deprecated
4171 public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String subString, boolean startsWith) throws TskCoreException {
4172 String valSubStr = "%" + subString; //NON-NLS
4173 if (startsWith == false) {
4174 valSubStr += "%"; //NON-NLS
4175 }
4176
4178 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement();
4179 ResultSet resultSet = connection.executeQuery(statement, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4180 + " 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
4181 + " types.type_name AS type_name, types.display_name AS display_name, " //NON-NLS
4182 + " arts.review_status_id AS review_status_id " //NON-NLS
4183 + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
4184 + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4185 + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
4186 + " AND LOWER(attrs.value_text) LIKE LOWER('" + valSubStr + "')"
4187 + " AND types.artifact_type_id=arts.artifact_type_id "
4188 + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());) {
4189 List<Long> analysisArtifactObjIds = new ArrayList<>();
4190 List<Long> dataArtifactObjIds = new ArrayList<>();
4191 while (resultSet.next()) {
4192 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
4193 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
4194 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4195 } else {
4196 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4197 }
4198 }
4199
4200 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4201 if (!analysisArtifactObjIds.isEmpty()) {
4202 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
4203 }
4204
4205 if (!dataArtifactObjIds.isEmpty()) {
4206 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
4207 }
4208 return artifacts;
4209 } catch (SQLException ex) {
4210 throw new TskCoreException("Error getting blackboard artifacts by attribute. " + ex.getMessage(), ex);
4211 } finally {
4213 }
4214 }
4215
4231 @Deprecated
4232 public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, int value) throws TskCoreException {
4234 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement();
4235 ResultSet resultSet = connection.executeQuery(statement, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4236 + " 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, "
4237 + " types.type_name AS type_name, types.display_name AS display_name, "
4238 + " arts.review_status_id AS review_status_id "//NON-NLS
4239 + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
4240 + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4241 + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
4242 + " AND attrs.value_int32 = " + value //NON-NLS
4243 + " AND types.artifact_type_id=arts.artifact_type_id "
4244 + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());) {
4245 List<Long> analysisArtifactObjIds = new ArrayList<>();
4246 List<Long> dataArtifactObjIds = new ArrayList<>();
4247 while (resultSet.next()) {
4248 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
4249 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
4250 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4251 } else {
4252 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4253 }
4254 }
4255
4256 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4257 if (!analysisArtifactObjIds.isEmpty()) {
4258 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
4259 }
4260
4261 if (!dataArtifactObjIds.isEmpty()) {
4262 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
4263 }
4264 return artifacts;
4265 } catch (SQLException ex) {
4266 throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
4267 } finally {
4269 }
4270 }
4271
4288 @Deprecated
4289 public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, long value) throws TskCoreException {
4291 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement();
4292 ResultSet resultSet = connection.executeQuery(statement, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4293 + " 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, "
4294 + " types.type_name AS type_name, types.display_name AS display_name, "
4295 + " arts.review_status_id AS review_status_id "//NON-NLS
4296 + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
4297 + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4298 + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
4299 + " AND attrs.value_int64 = " + value //NON-NLS
4300 + " AND types.artifact_type_id=arts.artifact_type_id "
4301 + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());) {
4302 List<Long> analysisArtifactObjIds = new ArrayList<>();
4303 List<Long> dataArtifactObjIds = new ArrayList<>();
4304 while (resultSet.next()) {
4305 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
4306 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
4307 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4308 } else {
4309 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4310 }
4311 }
4312
4313 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4314 if (!analysisArtifactObjIds.isEmpty()) {
4315 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
4316 }
4317
4318 if (!dataArtifactObjIds.isEmpty()) {
4319 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
4320 }
4321 return artifacts;
4322 } catch (SQLException ex) {
4323 throw new TskCoreException("Error getting blackboard artifacts by attribute. " + ex.getMessage(), ex);
4324 } finally {
4326 }
4327 }
4328
4345 @Deprecated
4346 public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, double value) throws TskCoreException {
4348 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement();
4349 ResultSet resultSet = connection.executeQuery(statement, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4350 + " 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, "
4351 + " types.type_name AS type_name, types.display_name AS display_name, "
4352 + " arts.review_status_id AS review_status_id "//NON-NLS
4353 + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
4354 + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4355 + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
4356 + " AND attrs.value_double = " + value //NON-NLS
4357 + " AND types.artifact_type_id=arts.artifact_type_id "
4358 + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());) {
4359 List<Long> analysisArtifactObjIds = new ArrayList<>();
4360 List<Long> dataArtifactObjIds = new ArrayList<>();
4361 while (resultSet.next()) {
4362 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
4363 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
4364 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4365 } else {
4366 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4367 }
4368 }
4369
4370 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4371 if (!analysisArtifactObjIds.isEmpty()) {
4372 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
4373 }
4374
4375 if (!dataArtifactObjIds.isEmpty()) {
4376 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
4377 }
4378 return artifacts;
4379 } catch (SQLException ex) {
4380 throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
4381 } finally {
4383 }
4384 }
4385
4402 @Deprecated
4403 public List<BlackboardArtifact> getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, byte value) throws TskCoreException {
4404
4406 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement();
4407 ResultSet resultSet = connection.executeQuery(statement, "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4408 + " 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, "
4409 + " types.type_name AS type_name, types.display_name AS display_name, "
4410 + " arts.review_status_id AS review_status_id "//NON-NLS
4411 + " FROM blackboard_artifacts AS arts, blackboard_attributes AS attrs, blackboard_artifact_types AS types " //NON-NLS
4412 + " WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4413 + " AND attrs.attribute_type_id = " + attrType.getTypeID() //NON-NLS
4414 + " AND attrs.value_byte = " + value //NON-NLS
4415 + " AND types.artifact_type_id=arts.artifact_type_id "
4416 + " AND arts.review_status_id !=" + BlackboardArtifact.ReviewStatus.REJECTED.getID());) {
4417 List<Long> analysisArtifactObjIds = new ArrayList<>();
4418 List<Long> dataArtifactObjIds = new ArrayList<>();
4419 while (resultSet.next()) {
4420 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
4421 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
4422 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4423 } else {
4424 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
4425 }
4426 }
4427
4428 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4429 if (!analysisArtifactObjIds.isEmpty()) {
4430 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
4431 }
4432
4433 if (!dataArtifactObjIds.isEmpty()) {
4434 artifacts.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
4435 }
4436 return artifacts;
4437 } catch (SQLException ex) {
4438 throw new TskCoreException("Error getting blackboard artifacts by attribute", ex);
4439 } finally {
4441 }
4442 }
4443
4452 CaseDbConnection connection = null;
4453 Statement s = null;
4454 ResultSet rs = null;
4456 try {
4457 connection = connections.getConnection();
4458 s = connection.createStatement();
4459 rs = connection.executeQuery(s, "SELECT artifact_type_id, type_name, display_name, category_type FROM blackboard_artifact_types"); //NON-NLS
4460 ArrayList<BlackboardArtifact.Type> artifactTypes = new ArrayList<BlackboardArtifact.Type>();
4461 while (rs.next()) {
4462 artifactTypes.add(new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
4463 rs.getString("type_name"), rs.getString("display_name"),
4464 BlackboardArtifact.Category.fromID(rs.getInt("category_type"))));
4465 }
4466 return artifactTypes;
4467 } catch (SQLException ex) {
4468 throw new TskCoreException("Error getting artifact types", ex); //NON-NLS
4469 } finally {
4470 closeResultSet(rs);
4471 closeStatement(s);
4472 closeConnection(connection);
4474 }
4475 }
4476
4486 String typeIdList = "";
4487 for (int i = 0; i < BlackboardArtifact.ARTIFACT_TYPE.values().length; ++i) {
4488 typeIdList += BlackboardArtifact.ARTIFACT_TYPE.values()[i].getTypeID();
4489 if (i < BlackboardArtifact.ARTIFACT_TYPE.values().length - 1) {
4490 typeIdList += ", ";
4491 }
4492 }
4493 String query = "SELECT DISTINCT artifact_type_id FROM blackboard_artifacts "
4494 + "WHERE artifact_type_id IN (" + typeIdList + ")";
4495 CaseDbConnection connection = null;
4496 Statement s = null;
4497 ResultSet rs = null;
4499 try {
4500 connection = connections.getConnection();
4501 s = connection.createStatement();
4502 rs = connection.executeQuery(s, query);
4503 ArrayList<BlackboardArtifact.ARTIFACT_TYPE> usedArts = new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>();
4504 while (rs.next()) {
4505 usedArts.add(ARTIFACT_TYPE.fromID(rs.getInt("artifact_type_id")));
4506 }
4507 return usedArts;
4508 } catch (SQLException ex) {
4509 throw new TskCoreException("Error getting artifact types in use", ex);
4510 } finally {
4511 closeResultSet(rs);
4512 closeStatement(s);
4513 closeConnection(connection);
4515 }
4516 }
4517
4529 CaseDbConnection connection = null;
4530 Statement s = null;
4531 ResultSet rs = null;
4533 try {
4534 connection = connections.getConnection();
4535 s = connection.createStatement();
4536 rs = connection.executeQuery(s,
4537 "SELECT DISTINCT arts.artifact_type_id AS artifact_type_id, "
4538 + "types.type_name AS type_name, "
4539 + "types.display_name AS display_name, "
4540 + "types.category_type AS category_type "
4541 + "FROM blackboard_artifact_types AS types "
4542 + "INNER JOIN blackboard_artifacts AS arts "
4543 + "ON arts.artifact_type_id = types.artifact_type_id"); //NON-NLS
4544 List<BlackboardArtifact.Type> uniqueArtifactTypes = new ArrayList<BlackboardArtifact.Type>();
4545 while (rs.next()) {
4546 uniqueArtifactTypes.add(new BlackboardArtifact.Type(rs.getInt("artifact_type_id"),
4547 rs.getString("type_name"), rs.getString("display_name"),
4548 BlackboardArtifact.Category.fromID(rs.getInt("category_type"))));
4549 }
4550 return uniqueArtifactTypes;
4551 } catch (SQLException ex) {
4552 throw new TskCoreException("Error getting attribute types", ex);
4553 } finally {
4554 closeResultSet(rs);
4555 closeStatement(s);
4556 closeConnection(connection);
4558 }
4559 }
4560
4569 CaseDbConnection connection = null;
4570 Statement s = null;
4571 ResultSet rs = null;
4573 try {
4574 connection = connections.getConnection();
4575 s = connection.createStatement();
4576 rs = connection.executeQuery(s, "SELECT attribute_type_id, type_name, display_name, value_type FROM blackboard_attribute_types"); //NON-NLS
4577 ArrayList<BlackboardAttribute.Type> attribute_types = new ArrayList<BlackboardAttribute.Type>();
4578 while (rs.next()) {
4579 attribute_types.add(new BlackboardAttribute.Type(rs.getInt("attribute_type_id"), rs.getString("type_name"),
4580 rs.getString("display_name"), TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.fromType(rs.getLong("value_type"))));
4581 }
4582 return attribute_types;
4583 } catch (SQLException ex) {
4584 throw new TskCoreException("Error getting attribute types", ex);
4585 } finally {
4586 closeResultSet(rs);
4587 closeStatement(s);
4588 closeConnection(connection);
4590 }
4591 }
4592
4605 CaseDbConnection connection = null;
4606 Statement s = null;
4607 ResultSet rs = null;
4609 try {
4610 connection = connections.getConnection();
4611 s = connection.createStatement();
4612 rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM blackboard_attribute_types"); //NON-NLS
4613 int count = 0;
4614 if (rs.next()) {
4615 count = rs.getInt("count");
4616 }
4617 return count;
4618 } catch (SQLException ex) {
4619 throw new TskCoreException("Error getting number of blackboard artifacts by type", ex);
4620 } finally {
4621 closeResultSet(rs);
4622 closeStatement(s);
4623 closeConnection(connection);
4625 }
4626 }
4627
4640 private long getArtifactsCountHelper(int artifactTypeID, long obj_id) throws TskCoreException {
4641 CaseDbConnection connection = null;
4642 ResultSet rs = null;
4644 try {
4645 connection = connections.getConnection();
4646
4647 // SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND artifact_type_id = ?
4648 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_SOURCE_AND_TYPE);
4649 statement.clearParameters();
4650 statement.setLong(1, obj_id);
4651 statement.setInt(2, artifactTypeID);
4652 rs = connection.executeQuery(statement);
4653 long count = 0;
4654 if (rs.next()) {
4655 count = rs.getLong("count");
4656 }
4657 return count;
4658 } catch (SQLException ex) {
4659 throw new TskCoreException("Error getting blackboard artifact count", ex);
4660 } finally {
4661 closeResultSet(rs);
4662 closeConnection(connection);
4664 }
4665 }
4666
4679 public ArrayList<BlackboardArtifact> getBlackboardArtifacts(String artifactTypeName, long obj_id) throws TskCoreException {
4680 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4681 artifacts.addAll(blackboard.getArtifactsBySourceId(getArtifactType(artifactTypeName), obj_id));
4682 return artifacts;
4683 }
4684
4697 public ArrayList<BlackboardArtifact> getBlackboardArtifacts(int artifactTypeID, long obj_id) throws TskCoreException {
4698 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4699 artifacts.addAll(blackboard.getArtifactsBySourceId(blackboard.getArtifactType(artifactTypeID), obj_id));
4700 return artifacts;
4701 }
4702
4715 public ArrayList<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
4716 return getBlackboardArtifacts(artifactType.getTypeID(), obj_id);
4717 }
4718
4731 public long getBlackboardArtifactsCount(String artifactTypeName, long obj_id) throws TskCoreException {
4732 int artifactTypeID = this.getArtifactType(artifactTypeName).getTypeID();
4733 if (artifactTypeID == -1) {
4734 return 0;
4735 }
4736 return getArtifactsCountHelper(artifactTypeID, obj_id);
4737 }
4738
4751 public long getBlackboardArtifactsCount(int artifactTypeID, long obj_id) throws TskCoreException {
4752 return getArtifactsCountHelper(artifactTypeID, obj_id);
4753 }
4754
4767 public long getBlackboardArtifactsCount(ARTIFACT_TYPE artifactType, long obj_id) throws TskCoreException {
4768 return getArtifactsCountHelper(artifactType.getTypeID(), obj_id);
4769 }
4770
4782 public ArrayList<BlackboardArtifact> getBlackboardArtifacts(String artifactTypeName) throws TskCoreException {
4783 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4784 artifacts.addAll(blackboard.getArtifactsByType(getArtifactType(artifactTypeName)));
4785 return artifacts;
4786 }
4787
4799 public ArrayList<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType) throws TskCoreException {
4800 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4801 artifacts.addAll(blackboard.getArtifactsByType(blackboard.getArtifactType(artifactType.getTypeID())));
4802 return artifacts;
4803 }
4804
4820 @Deprecated
4821 public List<BlackboardArtifact> getBlackboardArtifacts(ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value) throws TskCoreException {
4822
4823 String dataArtifactJoin = "tsk_data_artifacts AS datarts ON datarts.artifact_obj_id = arts.artifact_obj_id";
4824 String analysisResultJoin = "tsk_analysis_results AS anresult ON anresult.artifact_obj_id = arts.artifact_obj_id";
4825 String dataArtifactColumns = ", datarts.os_account_obj_id AS os_account_obj_id";
4826 String analysResultColumns = ", anresult.conclusion AS conclusion, anresult.significance AS significance, anresult.priority AS priority, anresult.configuration AS configuration, anresult.justification AS justification ";
4827
4828 String formatQuery = "SELECT DISTINCT arts.artifact_id AS artifact_id, " //NON-NLS
4829 + "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, "
4830 + "types.type_name AS type_name, types.display_name AS display_name,"
4831 + "arts.review_status_id AS review_status_id %s "//NON-NLS
4832 + "FROM blackboard_artifacts AS arts "
4833 + "JOIN blackboard_attributes AS attrs ON arts.artifact_id = attrs.artifact_id "
4834 + "JOIN blackboard_artifact_types AS types ON types.artifact_type_id = arts.artifact_type_id " //NON-NLS
4835 + "LEFT JOIN %s "
4836 + "WHERE arts.artifact_id = attrs.artifact_id " //NON-NLS
4837 + "AND attrs.attribute_type_id = %d "
4838 + " AND arts.artifact_type_id = %d "
4839 + " AND attrs.value_text = '%s' " //NON-NLS
4840 + " AND types.artifact_type_id=arts.artifact_type_id "
4841 + " AND arts.review_status_id != %d";
4842
4843 String query = String.format(formatQuery,
4844 (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT ? analysResultColumns : dataArtifactColumns),
4845 (artifactType.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT ? analysisResultJoin : dataArtifactJoin),
4846 attrType.getTypeID(),
4847 artifactType.getTypeID(),
4848 value,
4850
4852 try (CaseDbConnection connection = connections.getConnection(); Statement s = connection.createStatement(); ResultSet rs = connection.executeQuery(s, query)) {
4853 ArrayList<BlackboardArtifact> artifacts = new ArrayList<>();
4854 while (rs.next()) {
4855 if (artifactType.getCategory() == BlackboardArtifact.Category.DATA_ARTIFACT) {
4856 Long osAccountObjId = rs.getLong("os_account_obj_id");
4857 if (rs.wasNull()) {
4858 osAccountObjId = null;
4859 }
4860
4861 artifacts.add(new DataArtifact(this, rs.getLong("artifact_id"), rs.getLong("obj_id"),
4862 rs.getLong("artifact_obj_id"),
4863 rs.getObject("data_source_obj_id") != null ? rs.getLong("data_source_obj_id") : null,
4864 rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
4865 BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")), osAccountObjId, false));
4866 } else {
4867 artifacts.add(new AnalysisResult(this, rs.getLong("artifact_id"), rs.getLong("obj_id"),
4868 rs.getLong("artifact_obj_id"),
4869 rs.getObject("data_source_obj_id") != null ? rs.getLong("data_source_obj_id") : null,
4870 rs.getInt("artifact_type_id"), rs.getString("type_name"), rs.getString("display_name"),
4871 BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")),
4872 new Score(Score.Significance.fromID(rs.getInt("significance")), Score.Priority.fromID(rs.getInt("priority"))),
4873 rs.getString("conclusion"), rs.getString("configuration"), rs.getString("justification")));
4874 }
4875 }
4876 return artifacts;
4877 } catch (SQLException ex) {
4878 throw new TskCoreException("Error getting blackboard artifacts by artifact type and attribute. " + ex.getMessage(), ex);
4879 } finally {
4881 }
4882 }
4883
4896 List<DataArtifact> dataArtifacts = blackboard.getDataArtifactsWhere("artifacts.artifact_id = " + artifactID);
4897 if (!dataArtifacts.isEmpty()) {
4898 return dataArtifacts.get(0);
4899 }
4900
4901 List<AnalysisResult> analysisResults = blackboard.getAnalysisResultsWhere("artifacts.artifact_id = " + artifactID);
4902 if (!analysisResults.isEmpty()) {
4903 return analysisResults.get(0);
4904 }
4905
4906 throw new TskCoreException("No blackboard artifact with id " + artifactID);
4907 }
4908
4917 public void addBlackboardAttribute(BlackboardAttribute attr, int artifactTypeId) throws TskCoreException {
4919 try (CaseDbConnection connection = connections.getConnection();) {
4920 addBlackBoardAttribute(attr, artifactTypeId, connection);
4921 } catch (SQLException ex) {
4922 throw new TskCoreException("Error adding blackboard attribute " + attr.toString(), ex);
4923 } finally {
4925 }
4926 }
4927
4937 public void addBlackboardAttributes(Collection<BlackboardAttribute> attributes, int artifactTypeId) throws TskCoreException {
4938 CaseDbConnection connection = null;
4940 try {
4941 connection = connections.getConnection();
4942 connection.beginTransaction();
4943 for (final BlackboardAttribute attr : attributes) {
4944 addBlackBoardAttribute(attr, artifactTypeId, connection);
4945 }
4946 connection.commitTransaction();
4947 } catch (SQLException ex) {
4948 rollbackTransaction(connection);
4949 throw new TskCoreException("Error adding blackboard attributes", ex);
4950 } finally {
4951 closeConnection(connection);
4953 }
4954 }
4955
4956 void addBlackBoardAttribute(BlackboardAttribute attr, int artifactTypeId, CaseDbConnection connection) throws SQLException, TskCoreException {
4957 PreparedStatement statement;
4958 switch (attr.getAttributeType().getValueType()) {
4959 case STRING:
4960 case JSON:
4961 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_STRING_ATTRIBUTE);
4962 statement.clearParameters();
4963 statement.setString(7, attr.getValueString());
4964 break;
4965 case BYTE:
4966 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_BYTE_ATTRIBUTE);
4967 statement.clearParameters();
4968 statement.setBytes(7, attr.getValueBytes());
4969 break;
4970 case INTEGER:
4971 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INT_ATTRIBUTE);
4972 statement.clearParameters();
4973 statement.setInt(7, attr.getValueInt());
4974 break;
4975 case LONG:
4976 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LONG_ATTRIBUTE);
4977 statement.clearParameters();
4978 statement.setLong(7, attr.getValueLong());
4979 break;
4980 case DOUBLE:
4981 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DOUBLE_ATTRIBUTE);
4982 statement.clearParameters();
4983 statement.setDouble(7, attr.getValueDouble());
4984 break;
4985 case DATETIME:
4986 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LONG_ATTRIBUTE);
4987 statement.clearParameters();
4988 statement.setLong(7, attr.getValueLong());
4989 break;
4990 default:
4991 throw new TskCoreException("Unrecognized artifact attribute value type");
4992 }
4993 statement.setLong(1, attr.getArtifactID());
4994 statement.setInt(2, artifactTypeId);
4995 statement.setString(3, attr.getSourcesCSV());
4996 statement.setString(4, "");
4997 statement.setInt(5, attr.getAttributeType().getTypeID());
4998 statement.setLong(6, attr.getAttributeType().getValueType().getType());
4999 connection.executeUpdate(statement);
5000 }
5001
5002 void addFileAttribute(Attribute attr, CaseDbConnection connection) throws SQLException, TskCoreException {
5003 PreparedStatement statement;
5004 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_ATTRIBUTE, Statement.RETURN_GENERATED_KEYS);
5005 statement.clearParameters();
5006
5007 statement.setLong(1, attr.getAttributeParentId());
5008 statement.setInt(2, attr.getAttributeType().getTypeID());
5009 statement.setLong(3, attr.getAttributeType().getValueType().getType());
5010
5011 if (attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE) {
5012 statement.setBytes(4, attr.getValueBytes());
5013 } else {
5014 statement.setBytes(4, null);
5015 }
5016
5017 if (attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING
5018 || attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.JSON) {
5019 statement.setString(5, attr.getValueString());
5020 } else {
5021 statement.setString(5, null);
5022 }
5023 if (attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.INTEGER) {
5024 statement.setInt(6, attr.getValueInt());
5025 } else {
5026 statement.setNull(6, java.sql.Types.INTEGER);
5027 }
5028
5029 if (attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DATETIME
5030 || attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.LONG) {
5031 statement.setLong(7, attr.getValueLong());
5032 } else {
5033 statement.setNull(7, java.sql.Types.BIGINT);
5034 }
5035
5036 if (attr.getAttributeType().getValueType() == TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.DOUBLE) {
5037 statement.setDouble(8, attr.getValueDouble());
5038 } else {
5039 statement.setNull(8, java.sql.Types.DOUBLE);
5040 }
5041
5042 connection.executeUpdate(statement);
5043 try (ResultSet resultSet = statement.getGeneratedKeys()) {
5044 if (!resultSet.next()) {
5045 throw new TskCoreException(String.format("Failed to insert file attribute "
5046 + "with id=%d. The expected key was not generated", attr.getId()));
5047 }
5048
5049 attr.setId(resultSet.getLong(1));
5050 }
5051 }
5052
5063 String addSourceToArtifactAttribute(BlackboardAttribute attr, String source) throws TskCoreException {
5064 /*
5065 * WARNING: This is a temporary implementation that is not safe and
5066 * denormalizes the case datbase.
5067 *
5068 * TODO (JIRA-2294): Provide a safe and normalized solution to tracking
5069 * the sources of artifact attributes.
5070 */
5071 if (null == source || source.isEmpty()) {
5072 throw new TskCoreException("Attempt to add null or empty source module name to artifact attribute");
5073 }
5074 CaseDbConnection connection = null;
5076 Statement queryStmt = null;
5077 Statement updateStmt = null;
5078 ResultSet result = null;
5079 String newSources = "";
5080 try {
5081 connection = connections.getConnection();
5082 connection.beginTransaction();
5083 String valueClause = "";
5084 BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType = attr.getAttributeType().getValueType();
5085 if (BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE != valueType) {
5086 switch (valueType) {
5087 case STRING:
5088 case JSON:
5089 valueClause = " value_text = '" + escapeSingleQuotes(attr.getValueString()) + "'";
5090 break;
5091 case INTEGER:
5092 valueClause = " value_int32 = " + attr.getValueInt();
5093 break;
5094 case LONG:
5095 case DATETIME:
5096 valueClause = " value_int64 = " + attr.getValueLong();
5097 break;
5098 case DOUBLE:
5099 valueClause = " value_double = " + attr.getValueDouble();
5100 break;
5101 default:
5102 throw new TskCoreException(String.format("Unrecognized value type for attribute %s", attr.getDisplayString()));
5103 }
5104 String query = "SELECT source FROM blackboard_attributes WHERE"
5105 + " artifact_id = " + attr.getArtifactID()
5106 + " AND attribute_type_id = " + attr.getAttributeType().getTypeID()
5107 + " AND value_type = " + attr.getAttributeType().getValueType().getType()
5108 + " AND " + valueClause + ";";
5109 queryStmt = connection.createStatement();
5110 updateStmt = connection.createStatement();
5111 result = connection.executeQuery(queryStmt, query);
5112 } else {
5113 /*
5114 * SELECT source FROM blackboard_attributes WHERE artifact_id =
5115 * ? AND attribute_type_id = ? AND value_type = 4 AND value_byte
5116 * = ?
5117 */
5118 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ATTR_BY_VALUE_BYTE);
5119 statement.clearParameters();
5120 statement.setLong(1, attr.getArtifactID());
5121 statement.setLong(2, attr.getAttributeType().getTypeID());
5122 statement.setBytes(3, attr.getValueBytes());
5123 result = connection.executeQuery(statement);
5124 }
5125 while (result.next()) {
5126 String oldSources = result.getString("source");
5127 if (null != oldSources && !oldSources.isEmpty()) {
5128 Set<String> uniqueSources = new HashSet<String>(Arrays.asList(oldSources.split(",")));
5129 if (!uniqueSources.contains(source)) {
5130 newSources = oldSources + "," + source;
5131 } else {
5132 newSources = oldSources;
5133 }
5134 } else {
5135 newSources = source;
5136 }
5137 if (BlackboardAttribute.TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.BYTE != valueType) {
5138 String update = "UPDATE blackboard_attributes SET source = '" + newSources + "' WHERE"
5139 + " artifact_id = " + attr.getArtifactID()
5140 + " AND attribute_type_id = " + attr.getAttributeType().getTypeID()
5141 + " AND value_type = " + attr.getAttributeType().getValueType().getType()
5142 + " AND " + valueClause + ";";
5143 connection.executeUpdate(updateStmt, update);
5144 } else {
5145 /*
5146 * UPDATE blackboard_attributes SET source = ? WHERE
5147 * artifact_id = ? AND attribute_type_id = ? AND value_type
5148 * = 4 AND value_byte = ?
5149 */
5150 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ATTR_BY_VALUE_BYTE);
5151 statement.clearParameters();
5152 statement.setString(1, newSources);
5153 statement.setLong(2, attr.getArtifactID());
5154 statement.setLong(3, attr.getAttributeType().getTypeID());
5155 statement.setBytes(4, attr.getValueBytes());
5156 connection.executeUpdate(statement);
5157 }
5158 }
5159 connection.commitTransaction();
5160 return newSources;
5161 } catch (SQLException ex) {
5162 rollbackTransaction(connection);
5163 throw new TskCoreException(String.format("Error adding source module to attribute %s", attr.getDisplayString()), ex);
5164 } finally {
5165 closeResultSet(result);
5166 closeStatement(updateStmt);
5167 closeStatement(queryStmt);
5168 closeConnection(connection);
5170 }
5171 }
5172
5187 @Deprecated
5189 try {
5190 return blackboard.getOrAddAttributeType(attrTypeString, valueType, displayName);
5191 } catch (BlackboardException ex) {
5192 throw new TskCoreException("Error adding artifact type: " + attrTypeString, ex);
5193 }
5194 }
5195
5207 @Deprecated
5209 return blackboard.getAttributeType(attrTypeName);
5210 }
5211
5223 @Deprecated
5225 return blackboard.getArtifactType(artTypeName);
5226 }
5227
5244 @Deprecated
5245 public BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName) throws TskCoreException, TskDataException {
5246 return addBlackboardArtifactType(artifactTypeName, displayName, BlackboardArtifact.Category.DATA_ARTIFACT);
5247 }
5248
5264 @Deprecated
5265 BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName, BlackboardArtifact.Category category) throws TskCoreException, TskDataException {
5266 try {
5267 return blackboard.getOrAddArtifactType(displayName, displayName, category);
5268 } catch (BlackboardException ex) {
5269 throw new TskCoreException("Error getting or adding artifact type with name: " + artifactTypeName, ex);
5270 }
5271 }
5272
5284 @Deprecated
5285 public ArrayList<BlackboardAttribute> getBlackboardAttributes(final BlackboardArtifact artifact) throws TskCoreException {
5286 return blackboard.getBlackboardAttributes(artifact);
5287 }
5288
5289
5302 public ArrayList<BlackboardAttribute> getMatchingAttributes(String whereClause) throws TskCoreException {
5303 CaseDbConnection connection = null;
5304 Statement s = null;
5305 ResultSet rs = null;
5307 try {
5308 connection = connections.getConnection();
5309 s = connection.createStatement();
5310 rs = connection.executeQuery(s, "SELECT blackboard_attributes.artifact_id AS artifact_id, "
5311 + "blackboard_attributes.source AS source, blackboard_attributes.context AS context, "
5312 + "blackboard_attributes.attribute_type_id AS attribute_type_id, "
5313 + "blackboard_attributes.value_type AS value_type, blackboard_attributes.value_byte AS value_byte, "
5314 + "blackboard_attributes.value_text AS value_text, blackboard_attributes.value_int32 AS value_int32, "
5315 + "blackboard_attributes.value_int64 AS value_int64, blackboard_attributes.value_double AS value_double "
5316 + "FROM blackboard_attributes " + whereClause); //NON-NLS
5317 ArrayList<BlackboardAttribute> matches = new ArrayList<>();
5318 while (rs.next()) {
5320 // attribute type is cached, so this does not necessarily call to the db
5321 type = blackboard.getAttributeType(rs.getInt("attribute_type_id"));
5323 rs.getLong("artifact_id"),
5324 type,
5325 rs.getString("source"),
5326 rs.getString("context"),
5327 rs.getInt("value_int32"),
5328 rs.getLong("value_int64"),
5329 rs.getDouble("value_double"),
5330 rs.getString("value_text"),
5331 rs.getBytes("value_byte"), this
5332 );
5333 matches.add(attr);
5334 }
5335 return matches;
5336 } catch (SQLException ex) {
5337 throw new TskCoreException("Error getting attributes using this where clause: " + whereClause, ex);
5338 } finally {
5339 closeResultSet(rs);
5340 closeStatement(s);
5341 closeConnection(connection);
5343 }
5344 }
5345
5357 public ArrayList<BlackboardArtifact> getMatchingArtifacts(String whereClause) throws TskCoreException {
5358 String query = "SELECT blackboard_artifacts.artifact_id AS artifact_id, "
5359 + "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, "
5360 + "blackboard_artifacts.review_status_id AS review_status_id "
5361 + "FROM blackboard_artifacts " + whereClause;
5363 try (CaseDbConnection connection = connections.getConnection(); Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(query)) {
5364
5365 List<Long> analysisArtifactObjIds = new ArrayList<>();
5366 List<Long> dataArtifactObjIds = new ArrayList<>();
5367 while (resultSet.next()) {
5368 BlackboardArtifact.Type type = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
5369 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
5370 analysisArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
5371 } else {
5372 dataArtifactObjIds.add(resultSet.getLong("artifact_obj_id"));
5373 }
5374 }
5375
5376 ArrayList<BlackboardArtifact> matches = new ArrayList<>();
5377 if (!analysisArtifactObjIds.isEmpty()) {
5378 matches.addAll(getArtifactsForValues(BlackboardArtifact.Category.ANALYSIS_RESULT, "artifacts.artifact_obj_id", analysisArtifactObjIds, connection));
5379 }
5380
5381 if (!dataArtifactObjIds.isEmpty()) {
5382 matches.addAll(getArtifactsForValues(BlackboardArtifact.Category.DATA_ARTIFACT, "artifacts.artifact_obj_id", dataArtifactObjIds, connection));
5383 }
5384
5385 return matches;
5386 } catch (SQLException ex) {
5387 throw new TskCoreException("Error getting attributes using this where clause: " + whereClause, ex);
5388 } finally {
5390 }
5391 }
5392
5407 @Deprecated
5408 public BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id) throws TskCoreException {
5409 BlackboardArtifact.Type type = blackboard.getArtifactType(artifactTypeID);
5410 if (type == null) {
5411 throw new TskCoreException("Unknown artifact type for id: " + artifactTypeID);
5412 }
5413
5414 Category category = type.getCategory();
5415 if (category == null) {
5416 throw new TskCoreException(String.format("No category for %s (id: %d)",
5417 type.getDisplayName() == null ? "<null>" : type.getDisplayName(),
5418 type.getTypeID()));
5419 }
5420
5421 Content content = getContentById(obj_id);
5422 if (content == null) {
5423 throw new TskCoreException("No content found for object id: " + obj_id);
5424 }
5425
5426 switch (category) {
5427 case ANALYSIS_RESULT:
5428 return content.newAnalysisResult(type, Score.SCORE_UNKNOWN, null, null, null, Collections.emptyList())
5430 case DATA_ARTIFACT:
5431 return content.newDataArtifact(type, Collections.emptyList());
5432 default:
5433 throw new TskCoreException("Unknown category type: " + category.getName());
5434 }
5435 }
5436
5449 @Deprecated
5450 @SuppressWarnings("deprecation")
5452 return newBlackboardArtifact(artifactType.getTypeID(), obj_id);
5453 }
5454
5470 @Deprecated
5471 @SuppressWarnings("deprecation")
5472 BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id, long data_source_obj_id) throws TskCoreException {
5473 BlackboardArtifact.Type type = blackboard.getArtifactType(artifactTypeID);
5474 try (CaseDbConnection connection = connections.getConnection()) {
5475 return newBlackboardArtifact(artifactTypeID, obj_id, type.getTypeName(), type.getDisplayName(), data_source_obj_id, connection);
5476 }
5477 }
5478
5479 @Deprecated
5480 private BlackboardArtifact newBlackboardArtifact(int artifact_type_id, long obj_id, String artifactTypeName, String artifactDisplayName) throws TskCoreException {
5481 try (CaseDbConnection connection = connections.getConnection()) {
5482 long data_source_obj_id = getDataSourceObjectId(connection, obj_id);
5483 return this.newBlackboardArtifact(artifact_type_id, obj_id, artifactTypeName, artifactDisplayName, data_source_obj_id, connection);
5484 }
5485 }
5486
5487 PreparedStatement createInsertArtifactStatement(int artifact_type_id, long obj_id, long artifact_obj_id, long data_source_obj_id, CaseDbConnection connection) throws TskCoreException, SQLException {
5488
5489 PreparedStatement statement;
5490 if (dbType == DbType.POSTGRESQL) {
5491 statement = connection.getPreparedStatement(PREPARED_STATEMENT.POSTGRESQL_INSERT_ARTIFACT, Statement.RETURN_GENERATED_KEYS);
5492 statement.clearParameters();
5493 statement.setLong(1, obj_id);
5494 statement.setLong(2, artifact_obj_id);
5495 statement.setLong(3, data_source_obj_id);
5496 statement.setInt(4, artifact_type_id);
5497 } else {
5498 statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_ARTIFACT, Statement.RETURN_GENERATED_KEYS);
5499 statement.clearParameters();
5500 this.nextArtifactId++;
5501 statement.setLong(1, this.nextArtifactId);
5502 statement.setLong(2, obj_id);
5503 statement.setLong(3, artifact_obj_id);
5504 statement.setLong(4, data_source_obj_id);
5505 statement.setInt(5, artifact_type_id);
5506 }
5507
5508 return statement;
5509 }
5510
5527 @Deprecated
5528 private BlackboardArtifact newBlackboardArtifact(int artifact_type_id, long obj_id, String artifactTypeName, String artifactDisplayName, long data_source_obj_id, CaseDbConnection connection) throws TskCoreException {
5529 BlackboardArtifact.Type type = blackboard.getArtifactType(artifact_type_id);
5530 try {
5531 if (type.getCategory() == BlackboardArtifact.Category.ANALYSIS_RESULT) {
5532 return blackboard.newAnalysisResult(type, obj_id, data_source_obj_id, Score.SCORE_UNKNOWN, null, null, null, Collections.emptyList()).getAnalysisResult();
5533 } else {
5534 return blackboard.newDataArtifact(type, obj_id, data_source_obj_id, Collections.emptyList(), null);
5535 }
5536 } catch (BlackboardException ex) {
5537 throw new TskCoreException("Error creating a blackboard artifact", ex);
5538 }
5539 }
5540
5559 AnalysisResult newAnalysisResult(BlackboardArtifact.Type artifactType, long objId, Long dataSourceObjId, Score score, String conclusion, String configuration, String justification, CaseDbConnection connection) throws TskCoreException {
5560
5561 if (artifactType.getCategory() != BlackboardArtifact.Category.ANALYSIS_RESULT) {
5562 throw new TskCoreException(String.format("Artifact type (name = %s) is not of the AnalysisResult category. ", artifactType.getTypeName()));
5563 }
5564
5565 long artifactID;
5567 try {
5568 // add a row in tsk_objects
5569 long artifactObjId = addObject(objId, TskData.ObjectType.ARTIFACT.getObjectType(), connection);
5570
5571 // add a row in blackboard_artifacts table
5572 PreparedStatement insertArtifactstatement;
5573 ResultSet resultSet = null;
5574 try {
5575 insertArtifactstatement = createInsertArtifactStatement(artifactType.getTypeID(), objId, artifactObjId, dataSourceObjId, connection);
5576 connection.executeUpdate(insertArtifactstatement);
5577 resultSet = insertArtifactstatement.getGeneratedKeys();
5578 resultSet.next();
5579 artifactID = resultSet.getLong(1); //last_insert_rowid()
5580
5581 // add a row in tsk_analysis_results if any data for it is set
5582 if (score.getSignificance() != Score.Significance.UNKNOWN
5583 || !StringUtils.isBlank(conclusion)
5584 || !StringUtils.isBlank(configuration)
5585 || !StringUtils.isBlank(justification)) {
5586
5587 PreparedStatement analysisResultsStatement;
5588
5589 analysisResultsStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_ANALYSIS_RESULT);
5590 analysisResultsStatement.clearParameters();
5591
5592 analysisResultsStatement.setLong(1, artifactObjId);
5593 analysisResultsStatement.setString(2, (conclusion != null) ? conclusion : "");
5594 analysisResultsStatement.setInt(3, score.getSignificance().getId());
5595 analysisResultsStatement.setInt(4, score.getPriority().getId());
5596 analysisResultsStatement.setString(5, (configuration != null) ? configuration : "");
5597 analysisResultsStatement.setString(6, (justification != null) ? justification : "");
5598
5599 connection.executeUpdate(analysisResultsStatement);
5600 }
5601
5602 return new AnalysisResult(this, artifactID, objId, artifactObjId, dataSourceObjId, artifactType.getTypeID(),
5603 artifactType.getTypeName(), artifactType.getDisplayName(),
5604 BlackboardArtifact.ReviewStatus.UNDECIDED, true,
5605 score, (conclusion != null) ? conclusion : "",
5606 (configuration != null) ? configuration : "", (justification != null) ? justification : "");
5607
5608 } finally {
5609 closeResultSet(resultSet);
5610 }
5611
5612 } catch (SQLException ex) {
5613 throw new TskCoreException("Error creating a analysis result", ex);
5614 } finally {
5616 }
5617 }
5618
5631 boolean getContentHasChildren(Content content) throws TskCoreException {
5632 CaseDbConnection connection = null;
5633 ResultSet rs = null;
5635 try {
5636 connection = connections.getConnection();
5637
5638 // SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?
5639 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CHILD_OBJECTS_BY_PARENT);
5640 statement.clearParameters();
5641 statement.setLong(1, content.getId());
5642 rs = connection.executeQuery(statement);
5643 boolean hasChildren = false;
5644 if (rs.next()) {
5645 hasChildren = rs.getInt("count") > 0;
5646 }
5647 return hasChildren;
5648 } catch (SQLException e) {
5649 throw new TskCoreException("Error checking for children of parent " + content, e);
5650 } finally {
5651 closeResultSet(rs);
5652 closeConnection(connection);
5654 }
5655 }
5656
5669 int getContentChildrenCount(Content content) throws TskCoreException {
5670
5671 if (!this.getHasChildren(content)) {
5672 return 0;
5673 }
5674
5675 CaseDbConnection connection = null;
5676 ResultSet rs = null;
5678 try {
5679 connection = connections.getConnection();
5680
5681 // SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?
5682 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CHILD_OBJECTS_BY_PARENT);
5683 statement.clearParameters();
5684 statement.setLong(1, content.getId());
5685 rs = connection.executeQuery(statement);
5686 int countChildren = -1;
5687 if (rs.next()) {
5688 countChildren = rs.getInt("count");
5689 }
5690 return countChildren;
5691 } catch (SQLException e) {
5692 throw new TskCoreException("Error checking for children of parent " + content, e);
5693 } finally {
5694 closeResultSet(rs);
5695 closeConnection(connection);
5697 }
5698 }
5699
5719 int getAbstractFileChildrenCountByType(Content content, List<TSK_FS_NAME_TYPE_ENUM> types) throws TskCoreException {
5720
5721 if (!this.getHasChildren(content)) {
5722 return 0;
5723 }
5724
5725 if (types == null || types.isEmpty()) {
5726 return 0;
5727 }
5728
5729 CaseDbConnection connection = null;
5730 ResultSet rs = null;
5732 try {
5733 connection = connections.getConnection();
5734
5735 // Construct the IN clause dynamically
5736 StringBuilder inClause = new StringBuilder("?");
5737 for (int i = 1; i < types.size(); i++) {
5738 inClause.append(", ?");
5739 }
5740
5741 String sql = "SELECT COUNT(*) AS count "
5742 + "FROM tsk_objects "
5743 + "INNER JOIN tsk_files ON tsk_objects.obj_id = tsk_files.obj_id "
5744 + "WHERE (tsk_objects.par_obj_id = ? AND tsk_files.dir_type IN (" + inClause.toString() + "))";
5745
5746 PreparedStatement statement = connection.getConnection().prepareStatement(sql);
5747 statement.clearParameters();
5748 statement.setLong(1, content.getId());
5749
5750 for (int i = 0; i < types.size(); i++) {
5751 statement.setInt(i + 2, types.get(i).getValue()); // Note: i+2 because index 1 is already taken by obj_id
5752 }
5753
5754 rs = connection.executeQuery(statement);
5755 int countChildren = -1;
5756 if (rs.next()) {
5757 countChildren = rs.getInt("count");
5758 }
5759 return countChildren;
5760 } catch (SQLException e) {
5761 throw new TskCoreException("Error checking for children of parent " + content, e);
5762 } finally {
5763 closeResultSet(rs);
5764 closeConnection(connection);
5766 }
5767 }
5768
5780 List<Content> getAbstractFileChildren(Content parent, TSK_DB_FILES_TYPE_ENUM type) throws TskCoreException {
5781 CaseDbConnection connection = null;
5782 ResultSet rs = null;
5784 try {
5785 connection = connections.getConnection();
5786
5787 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT_AND_TYPE);
5788 statement.clearParameters();
5789 long parentId = parent.getId();
5790 statement.setLong(1, parentId);
5791 statement.setShort(2, type.getFileType());
5792 rs = connection.executeQuery(statement);
5793 return fileChildren(rs, connection, parentId);
5794 } catch (SQLException ex) {
5795 throw new TskCoreException("Error getting AbstractFile children for Content", ex);
5796 } finally {
5797 closeResultSet(rs);
5798 closeConnection(connection);
5800 }
5801 }
5802
5812 List<Content> getAbstractFileChildren(Content parent) throws TskCoreException {
5813 CaseDbConnection connection = null;
5814 ResultSet rs = null;
5816 try {
5817 connection = connections.getConnection();
5818
5819 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT);
5820 statement.clearParameters();
5821 long parentId = parent.getId();
5822 statement.setLong(1, parentId);
5823 rs = connection.executeQuery(statement);
5824 return fileChildren(rs, connection, parentId);
5825 } catch (SQLException ex) {
5826 throw new TskCoreException("Error getting AbstractFile children for Content", ex);
5827 } finally {
5828 closeResultSet(rs);
5829 closeConnection(connection);
5831 }
5832 }
5833
5845 List<Long> getAbstractFileChildrenIds(Content parent, TSK_DB_FILES_TYPE_ENUM type) throws TskCoreException {
5846 CaseDbConnection connection = null;
5847 ResultSet rs = null;
5849 try {
5850 connection = connections.getConnection();
5851
5852 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_IDS_BY_PARENT_AND_TYPE);
5853 statement.clearParameters();
5854 statement.setLong(1, parent.getId());
5855 statement.setShort(2, type.getFileType());
5856 rs = connection.executeQuery(statement);
5857 List<Long> children = new ArrayList<Long>();
5858 while (rs.next()) {
5859 children.add(rs.getLong("obj_id"));
5860 }
5861 return children;
5862 } catch (SQLException ex) {
5863 throw new TskCoreException("Error getting AbstractFile children for Content", ex);
5864 } finally {
5865 closeResultSet(rs);
5866 closeConnection(connection);
5868 }
5869 }
5870
5880 List<Long> getAbstractFileChildrenIds(Content parent) throws TskCoreException {
5881 CaseDbConnection connection = null;
5882 ResultSet rs = null;
5884 try {
5885 connection = connections.getConnection();
5886
5887 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_IDS_BY_PARENT);
5888 statement.clearParameters();
5889 statement.setLong(1, parent.getId());
5890 rs = connection.executeQuery(statement);
5891 List<Long> children = new ArrayList<Long>();
5892 while (rs.next()) {
5893 children.add(rs.getLong("obj_id"));
5894 }
5895 return children;
5896 } catch (SQLException ex) {
5897 throw new TskCoreException("Error getting AbstractFile children for Content", ex);
5898 } finally {
5899 closeResultSet(rs);
5900 closeConnection(connection);
5902 }
5903 }
5904
5915 List<Long> getBlackboardArtifactChildrenIds(Content parent) throws TskCoreException {
5916 CaseDbConnection connection = null;
5917 ResultSet rs = null;
5919 try {
5920 connection = connections.getConnection();
5921
5922 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_OBJECTIDS_BY_PARENT);
5923 statement.clearParameters();
5924 statement.setLong(1, parent.getId());
5925 rs = connection.executeQuery(statement);
5926 List<Long> children = new ArrayList<Long>();
5927 while (rs.next()) {
5928 children.add(rs.getLong("obj_id"));
5929 }
5930 return children;
5931 } catch (SQLException ex) {
5932 throw new TskCoreException("Error getting children for BlackboardArtifact", ex);
5933 } finally {
5934 closeResultSet(rs);
5935 closeConnection(connection);
5937 }
5938 }
5939
5949 List<Content> getBlackboardArtifactChildren(Content parent) throws TskCoreException {
5950 long parentId = parent.getId();
5951 List<Content> lc = new ArrayList<>();
5952 lc.addAll(blackboard.getAnalysisResults(parentId));
5953 lc.addAll(blackboard.getDataArtifactsBySource(parentId));
5954 return lc;
5955 }
5956
5965 Collection<ObjectInfo> getChildrenInfo(Content c) throws TskCoreException {
5966 CaseDbConnection connection = null;
5967 Statement s = null;
5968 ResultSet rs = null;
5970 try {
5971 connection = connections.getConnection();
5972 s = connection.createStatement();
5973 rs = connection.executeQuery(s, "SELECT tsk_objects.obj_id AS obj_id, tsk_objects.type AS type " //NON-NLS
5974 + "FROM tsk_objects LEFT JOIN tsk_files " //NON-NLS
5975 + "ON tsk_objects.obj_id = tsk_files.obj_id " //NON-NLS
5976 + "WHERE tsk_objects.par_obj_id = " + c.getId()
5977 + " ORDER BY tsk_objects.obj_id"); //NON-NLS
5978 Collection<ObjectInfo> infos = new ArrayList<ObjectInfo>();
5979 while (rs.next()) {
5980 infos.add(new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")))); //NON-NLS
5981 }
5982 return infos;
5983 } catch (SQLException ex) {
5984 throw new TskCoreException("Error getting Children Info for Content", ex);
5985 } finally {
5986 closeResultSet(rs);
5987 closeStatement(s);
5988 closeConnection(connection);
5990 }
5991 }
5992
6003 ObjectInfo getParentInfo(Content c) throws TskCoreException {
6004 return getParentInfo(c.getId());
6005 }
6006
6017 ObjectInfo getParentInfo(long contentId) throws TskCoreException {
6019 CaseDbConnection connection = null;
6020 Statement s = null;
6021 ResultSet rs = null;
6022 try {
6023 connection = connections.getConnection();
6024 s = connection.createStatement();
6025 rs = connection.executeQuery(s, "SELECT parent.obj_id AS obj_id, parent.type AS type " //NON-NLS
6026 + "FROM tsk_objects AS parent INNER JOIN tsk_objects AS child " //NON-NLS
6027 + "ON child.par_obj_id = parent.obj_id " //NON-NLS
6028 + "WHERE child.obj_id = " + contentId); //NON-NLS
6029 if (rs.next()) {
6030 return new ObjectInfo(rs.getLong("obj_id"), ObjectType.valueOf(rs.getShort("type")));
6031 } else {
6032 return null;
6033 }
6034 } catch (SQLException ex) {
6035 throw new TskCoreException("Error getting Parent Info for Content: " + contentId, ex);
6036 } finally {
6037 closeResultSet(rs);
6038 closeStatement(s);
6039 closeConnection(connection);
6041 }
6042 }
6043
6054 Directory getParentDirectory(FsContent fsc) throws TskCoreException {
6055 if (fsc.isRoot()) {
6056 // Given FsContent is a root object and can't have parent directory
6057 return null;
6058 } else {
6059 ObjectInfo parentInfo = getParentInfo(fsc);
6060 if (parentInfo == null) {
6061 return null;
6062 }
6063 Directory parent = null;
6064 if (parentInfo.type == ObjectType.ABSTRACTFILE) {
6065 parent = getDirectoryById(parentInfo.id, fsc.getFileSystem());
6066 } else {
6067 throw new TskCoreException("Parent of FsContent (id: " + fsc.getId() + ") has wrong type to be directory: " + parentInfo.type);
6068 }
6069 return parent;
6070 }
6071 }
6072
6084 public Content getContentById(long id) throws TskCoreException {
6085 // First check to see if this exists in our frequently used content cache.
6086 Content content = frequentlyUsedContentMap.get(id);
6087 if (null != content) {
6088 return content;
6089 }
6090
6091 long parentId;
6092 TskData.ObjectType type;
6093
6094 CaseDbConnection connection = null;
6095 Statement s = null;
6096 ResultSet rs = null;
6098 try {
6099 connection = connections.getConnection();
6100 s = connection.createStatement();
6101 rs = connection.executeQuery(s, "SELECT * FROM tsk_objects WHERE obj_id = " + id + " LIMIT 1"); //NON-NLS
6102 if (!rs.next()) {
6103 return null;
6104 }
6105 parentId = rs.getLong("par_obj_id"); //NON-NLS
6106 type = TskData.ObjectType.valueOf(rs.getShort("type")); //NON-NLS
6107 } catch (SQLException ex) {
6108 throw new TskCoreException("Error getting Content by ID.", ex);
6109 } finally {
6110 closeResultSet(rs);
6111 closeStatement(s);
6112 closeConnection(connection);
6114 }
6115
6116 // Construct the object
6117 switch (type) {
6118 case IMG:
6119 content = getImageById(id);
6120 frequentlyUsedContentMap.put(id, content);
6121 break;
6122 case VS:
6123 content = getVolumeSystemById(id, parentId);
6124 break;
6125 case VOL:
6126 content = getVolumeById(id, parentId);
6127 frequentlyUsedContentMap.put(id, content);
6128 break;
6129 case POOL:
6130 content = getPoolById(id, parentId);
6131 break;
6132 case FS:
6133 content = getFileSystemById(id, parentId);
6134 frequentlyUsedContentMap.put(id, content);
6135 break;
6136 case ABSTRACTFILE:
6137 content = getAbstractFileById(id);
6138
6139 // Add virtual and root directories to frequently used map.
6140 // Calling isRoot() on local directories goes up the entire directory structure
6141 // and they can only be the root of portable cases, so skip trying to add
6142 // them to the cache.
6143 if (((AbstractFile) content).isVirtual()
6144 || ((!(content instanceof LocalDirectory)) && ((AbstractFile) content).isRoot())) {
6145 frequentlyUsedContentMap.put(id, content);
6146 }
6147 break;
6148 case ARTIFACT:
6149 content = getArtifactById(id);
6150 break;
6151 case REPORT:
6152 content = getReportById(id);
6153 break;
6154 case OS_ACCOUNT:
6155 content = this.osAccountManager.getOsAccountByObjectId(id);
6156 break;
6157 case HOST_ADDRESS:
6158 content = hostAddressManager.getHostAddress(id);
6159 break;
6160 default:
6161 content = new UnsupportedContent(this, id);
6162 }
6163
6164 return content;
6165 }
6166
6174 String getFilePath(long id) {
6175
6176 String filePath = null;
6177 CaseDbConnection connection = null;
6178 ResultSet rs = null;
6180 try {
6181 connection = connections.getConnection();
6182
6183 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_FOR_FILE);
6184 statement.clearParameters();
6185 statement.setLong(1, id);
6186 rs = connection.executeQuery(statement);
6187 if (rs.next()) {
6188 filePath = rs.getString("path");
6189 }
6190 } catch (SQLException | TskCoreException ex) {
6191 logger.log(Level.SEVERE, "Error getting file path for file " + id, ex); //NON-NLS
6192 } finally {
6193 closeResultSet(rs);
6194 closeConnection(connection);
6196 }
6197 return filePath;
6198 }
6199
6207 TskData.EncodingType getEncodingType(long id) {
6208
6209 TskData.EncodingType type = TskData.EncodingType.NONE;
6210 CaseDbConnection connection = null;
6211 ResultSet rs = null;
6213 try {
6214 connection = connections.getConnection();
6215 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ENCODING_FOR_FILE);
6216 statement.clearParameters();
6217 statement.setLong(1, id);
6218 rs = connection.executeQuery(statement);
6219 if (rs.next()) {
6220 type = TskData.EncodingType.valueOf(rs.getInt(1));
6221 }
6222 } catch (SQLException | TskCoreException ex) {
6223 logger.log(Level.SEVERE, "Error getting encoding type for file " + id, ex); //NON-NLS
6224 } finally {
6225 closeResultSet(rs);
6226 closeConnection(connection);
6228 }
6229 return type;
6230 }
6231
6240 String getFileParentPath(long objectId, CaseDbConnection connection) {
6241 String parentPath = null;
6243 ResultSet rs = null;
6244 try {
6245 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_PATH_FOR_FILE);
6246 statement.clearParameters();
6247 statement.setLong(1, objectId);
6248 rs = connection.executeQuery(statement);
6249 if (rs.next()) {
6250 parentPath = rs.getString("parent_path");
6251 }
6252 } catch (SQLException ex) {
6253 logger.log(Level.SEVERE, "Error getting file parent_path for file " + objectId, ex); //NON-NLS
6254 } finally {
6255 closeResultSet(rs);
6257 }
6258 return parentPath;
6259 }
6260
6269 String getFileName(long objectId, CaseDbConnection connection) {
6270 String fileName = null;
6272 ResultSet rs = null;
6273 try {
6274 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_NAME);
6275 statement.clearParameters();
6276 statement.setLong(1, objectId);
6277 rs = connection.executeQuery(statement);
6278 if (rs.next()) {
6279 fileName = rs.getString("name");
6280 }
6281 } catch (SQLException ex) {
6282 logger.log(Level.SEVERE, "Error getting file parent_path for file " + objectId, ex); //NON-NLS
6283 } finally {
6284 closeResultSet(rs);
6286 }
6287 return fileName;
6288 }
6289
6300 DerivedFile.DerivedMethod getDerivedMethod(long id) throws TskCoreException {
6301
6302 DerivedFile.DerivedMethod method = null;
6303 CaseDbConnection connection = null;
6304 ResultSet rs1 = null;
6305 ResultSet rs2 = null;
6307 try {
6308 connection = connections.getConnection();
6309
6310 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_DERIVED_FILE);
6311 statement.clearParameters();
6312 statement.setLong(1, id);
6313 rs1 = connection.executeQuery(statement);
6314 if (rs1.next()) {
6315 int method_id = rs1.getInt("derived_id");
6316 String rederive = rs1.getString("rederive");
6317 method = new DerivedFile.DerivedMethod(method_id, rederive);
6318 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_DERIVATION_METHOD);
6319 statement.clearParameters();
6320 statement.setInt(1, method_id);
6321 rs2 = connection.executeQuery(statement);
6322 if (rs2.next()) {
6323 method.setToolName(rs2.getString("tool_name"));
6324 method.setToolVersion(rs2.getString("tool_version"));
6325 method.setOther(rs2.getString("other"));
6326 }
6327 }
6328 } catch (SQLException e) {
6329 logger.log(Level.SEVERE, "Error getting derived method for file: " + id, e); //NON-NLS
6330 } finally {
6331 closeResultSet(rs2);
6332 closeResultSet(rs1);
6333 closeConnection(connection);
6335 }
6336 return method;
6337 }
6338
6350 CaseDbConnection connection = connections.getConnection();
6351 try {
6352 return getAbstractFileById(id, connection);
6353 } finally {
6354 closeConnection(connection);
6355 }
6356 }
6357
6370 AbstractFile getAbstractFileById(long objectId, CaseDbConnection connection) throws TskCoreException {
6372 ResultSet rs = null;
6373 try {
6374 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_BY_ID);
6375 statement.clearParameters();
6376 statement.setLong(1, objectId);
6377 rs = connection.executeQuery(statement);
6378 List<AbstractFile> files = resultSetToAbstractFiles(rs, connection);
6379 if (files.size() > 0) {
6380 return files.get(0);
6381 } else {
6382 return null;
6383 }
6384 } catch (SQLException ex) {
6385 throw new TskCoreException("Error getting file by id, id = " + objectId, ex);
6386 } finally {
6387 closeResultSet(rs);
6389 }
6390 }
6391
6404
6405 CaseDbConnection connection = null;
6406 ResultSet rs = null;
6408 try {
6409 connection = connections.getConnection();
6410
6411 // get the artifact type.
6412 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TYPE_BY_ARTIFACT_OBJ_ID);
6413 statement.clearParameters();
6414 statement.setLong(1, id);
6415
6416 rs = connection.executeQuery(statement);
6417 if (!rs.next()) {
6418 throw new TskCoreException("Error getting artifacttype for artifact with artifact_obj_id = " + id);
6419 }
6420
6421 // based on the artifact type category, get the analysis result or the data artifact
6422 BlackboardArtifact.Type artifactType = blackboard.getArtifactType(rs.getInt("artifact_type_id"));
6423 switch (artifactType.getCategory()) {
6424 case ANALYSIS_RESULT:
6425 return blackboard.getAnalysisResultById(id);
6426 case DATA_ARTIFACT:
6427 return blackboard.getDataArtifactById(id);
6428 default:
6429 throw new TskCoreException(String.format("Unknown artifact category for artifact with artifact_obj_id = %d, and artifact type = %s", id, artifactType.getTypeName()));
6430 }
6431
6432 } catch (SQLException ex) {
6433 throw new TskCoreException("Error getting artifacts by artifact_obj_id, artifact_obj_id = " + id, ex);
6434 } finally {
6435 closeResultSet(rs);
6436 closeConnection(connection);
6438 }
6439 }
6440
6454 @Deprecated
6456 String query = "SELECT artifact_type_id, artifact_obj_id FROM blackboard_artifacts WHERE artifact_id = " + id;
6458
6459 try (CaseDbConnection connection = connections.getConnection();
6460 Statement statement = connection.createStatement();
6461 ResultSet resultSet = statement.executeQuery(query);) {
6462 if (resultSet != null && resultSet.next()) {
6463 BlackboardArtifact.Type artifactType = blackboard.getArtifactType(resultSet.getInt("artifact_type_id"));
6464 long artifactObjId = resultSet.getLong("artifact_obj_id");
6465 switch (artifactType.getCategory()) {
6466 case ANALYSIS_RESULT:
6467 return blackboard.getAnalysisResultById(artifactObjId);
6468 case DATA_ARTIFACT:
6469 return blackboard.getDataArtifactById(artifactObjId);
6470 }
6471 }
6472 return null;
6473 } catch (SQLException ex) {
6474 throw new TskCoreException("Error getting artifacts by artifact id, artifact id = " + id, ex);
6475 } finally {
6477 }
6478 }
6479
6492 private long getFileSystemId(long fileId, CaseDbConnection connection) {
6494 ResultSet rs = null;
6495 long ret = -1;
6496 try {
6497 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILE_SYSTEM_BY_OBJECT);
6498 statement.clearParameters();
6499 statement.setLong(1, fileId);
6500 rs = connection.executeQuery(statement);
6501 if (rs.next()) {
6502 ret = rs.getLong("fs_obj_id");
6503 if (ret == 0) {
6504 ret = -1;
6505 }
6506 }
6507 } catch (SQLException e) {
6508 logger.log(Level.SEVERE, "Error checking file system id of a file, id = " + fileId, e); //NON-NLS
6509 } finally {
6510 closeResultSet(rs);
6512 }
6513 return ret;
6514 }
6515
6527 public boolean isFileFromSource(Content dataSource, long fileId) throws TskCoreException {
6528 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
6529 CaseDbConnection connection = null;
6530 Statement statement = null;
6531 ResultSet resultSet = null;
6533 try {
6534 connection = connections.getConnection();
6535 statement = connection.createStatement();
6536 resultSet = connection.executeQuery(statement, query);
6537 resultSet.next();
6538 return (resultSet.getLong("count") > 0L);
6539 } catch (SQLException ex) {
6540 throw new TskCoreException(String.format("Error executing query %s", query), ex);
6541 } finally {
6542 closeResultSet(resultSet);
6543 closeStatement(statement);
6544 closeConnection(connection);
6546 }
6547 }
6548
6558 private static boolean containsLikeWildcard(String str) {
6559 if (str == null) {
6560 return false;
6561 } else {
6562 return str.contains("%") || str.contains("_");
6563 }
6564 }
6565
6577 public List<AbstractFile> findFiles(Content dataSource, String fileName) throws TskCoreException {
6578 String ext = "";
6579 if (!containsLikeWildcard(fileName)) {
6580 ext = SleuthkitCase.extractExtension(fileName);
6581 }
6582
6583 List<AbstractFile> files = new ArrayList<>();
6584 CaseDbConnection connection = null;
6585 ResultSet resultSet = null;
6587 try {
6588 connection = connections.getConnection();
6589
6590 PreparedStatement statement;
6591 if (ext.isEmpty()) {
6592 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_DATA_SOURCE_AND_NAME);
6593 statement.clearParameters();
6594 statement.setString(1, fileName.toLowerCase());
6595 statement.setLong(2, dataSource.getId());
6596 } else {
6597 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_EXTENSION_AND_DATA_SOURCE_AND_NAME);
6598 statement.clearParameters();
6599 statement.setString(1, ext);
6600 statement.setString(2, fileName.toLowerCase());
6601 statement.setLong(3, dataSource.getId());
6602 }
6603
6604 resultSet = connection.executeQuery(statement);
6605 files.addAll(resultSetToAbstractFiles(resultSet, connection));
6606 } catch (SQLException e) {
6607 throw new TskCoreException(bundle.getString("SleuthkitCase.findFiles.exception.msg3.text"), e);
6608 } finally {
6609 closeResultSet(resultSet);
6610 closeConnection(connection);
6612 }
6613 return files;
6614 }
6615
6629 public List<AbstractFile> findFiles(Content dataSource, String fileName, String dirSubString) throws TskCoreException {
6630 String ext = "";
6631 if (!containsLikeWildcard(fileName)) {
6632 ext = SleuthkitCase.extractExtension(fileName);
6633 }
6634
6635 List<AbstractFile> files = new ArrayList<>();
6636 CaseDbConnection connection = null;
6637 ResultSet resultSet = null;
6639 try {
6640 connection = connections.getConnection();
6641 PreparedStatement statement;
6642 if (ext.isEmpty()) {
6643 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_DATA_SOURCE_AND_PARENT_PATH_AND_NAME);
6644 statement.clearParameters();
6645 statement.setString(1, fileName.toLowerCase());
6646 statement.setString(2, "%" + dirSubString.toLowerCase() + "%"); //NON-NLS
6647 statement.setLong(3, dataSource.getId());
6648 } else {
6650 statement.clearParameters();
6651 statement.setString(1, ext);
6652 statement.setString(2, fileName.toLowerCase());
6653 statement.setString(3, "%" + dirSubString.toLowerCase() + "%"); //NON-NLS
6654 statement.setLong(4, dataSource.getId());
6655 }
6656
6657 resultSet = connection.executeQuery(statement);
6658 files.addAll(resultSetToAbstractFiles(resultSet, connection));
6659 } catch (SQLException e) {
6660 throw new TskCoreException(bundle.getString("SleuthkitCase.findFiles3.exception.msg3.text"), e);
6661 } finally {
6662 closeResultSet(resultSet);
6663 closeConnection(connection);
6665 }
6666 return files;
6667 }
6668
6680 public VirtualDirectory addVirtualDirectory(long parentId, String directoryName) throws TskCoreException {
6681 CaseDbTransaction localTrans = beginTransaction();
6682 try {
6683 VirtualDirectory newVD = addVirtualDirectory(parentId, directoryName, localTrans);
6684 localTrans.commit();
6685 localTrans = null;
6686 return newVD;
6687 } finally {
6688 if (null != localTrans) {
6689 try {
6690 localTrans.rollback();
6691 } catch (TskCoreException ex2) {
6692 logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
6693 }
6694 }
6695 }
6696 }
6697
6710 long addObject(long parentId, int objectType, CaseDbConnection connection) throws SQLException {
6711 ResultSet resultSet = null;
6713 try {
6714 // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
6715 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_OBJECT, Statement.RETURN_GENERATED_KEYS);
6716 statement.clearParameters();
6717 if (parentId != 0) {
6718 statement.setLong(1, parentId);
6719 } else {
6720 statement.setNull(1, java.sql.Types.BIGINT);
6721 }
6722 statement.setInt(2, objectType);
6723 connection.executeUpdate(statement);
6724 resultSet = statement.getGeneratedKeys();
6725
6726 if (resultSet.next()) {
6727 if (parentId != 0) {
6728 setHasChildren(parentId);
6729 }
6730 return resultSet.getLong(1); //last_insert_rowid()
6731 } else {
6732 throw new SQLException("Error inserting object with parent " + parentId + " into tsk_objects");
6733 }
6734 } finally {
6735 closeResultSet(resultSet);
6737 }
6738 }
6739
6757 public VirtualDirectory addVirtualDirectory(long parentId, String directoryName, CaseDbTransaction transaction) throws TskCoreException {
6758 if (transaction == null) {
6759 throw new TskCoreException("Passed null CaseDbTransaction");
6760 }
6761
6762 ResultSet resultSet = null;
6763 try {
6764 // Get the parent path.
6765 CaseDbConnection connection = transaction.getConnection();
6766
6767 String parentPath;
6768 Content parent = this.getAbstractFileById(parentId, connection);
6769 if (parent instanceof AbstractFile) {
6770 if (isRootDirectory((AbstractFile) parent, transaction)) {
6771 if (parent.getName().isEmpty()) {
6772 parentPath = "/";
6773 } else {
6774 parentPath = "/" + parent.getName() + "/";
6775 }
6776 } else {
6777 parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + "/"; //NON-NLS
6778 }
6779 } else {
6780 // The parent was either null or not an abstract file
6781 parentPath = "/";
6782 }
6783
6784 // Insert a row for the virtual directory into the tsk_objects table.
6785 long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6786
6787 // Insert a row for the virtual directory into the tsk_files table.
6788 // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
6789 // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, sha1, known, mime_type, parent_path, data_source_obj_id,extension,owner_uid, os_account_obj_id)
6790 // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?,?,?)
6791 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6792 statement.clearParameters();
6793 statement.setLong(1, newObjId);
6794
6795 // If the parent is part of a file system, grab its file system ID
6796 Long fileSystemObjectId = null;
6797 if (0 != parentId) {
6798 fileSystemObjectId = this.getFileSystemId(parentId, connection);
6799 if (fileSystemObjectId != -1) {
6800 statement.setLong(2, fileSystemObjectId);
6801 } else {
6802 statement.setNull(2, java.sql.Types.BIGINT);
6803 fileSystemObjectId = null;
6804 }
6805 } else {
6806 statement.setNull(2, java.sql.Types.BIGINT);
6807 }
6808
6809 // name
6810 statement.setString(3, directoryName);
6811
6812 //type
6813 statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType());
6814 statement.setShort(5, (short) 1);
6815
6816 //flags
6818 statement.setShort(6, dirType.getValue());
6820 statement.setShort(7, metaType.getValue());
6821
6822 //allocated
6824 statement.setShort(8, dirFlag.getValue());
6825 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
6826 | TSK_FS_META_FLAG_ENUM.USED.getValue());
6827 statement.setShort(9, metaFlags);
6828
6829 //size
6830 statement.setLong(10, 0);
6831
6832 // nulls for params 11-14
6833 statement.setNull(11, java.sql.Types.BIGINT);
6834 statement.setNull(12, java.sql.Types.BIGINT);
6835 statement.setNull(13, java.sql.Types.BIGINT);
6836 statement.setNull(14, java.sql.Types.BIGINT);
6837
6838 statement.setNull(15, java.sql.Types.VARCHAR); // MD5
6839 statement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
6840 statement.setNull(17, java.sql.Types.VARCHAR); // SHA-1
6841
6842 statement.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6843 statement.setNull(19, java.sql.Types.VARCHAR); // MIME type
6844
6845 // parent path
6846 statement.setString(20, parentPath);
6847
6848 // data source object id (same as object id if this is a data source)
6849 long dataSourceObjectId;
6850 if (0 == parentId) {
6851 dataSourceObjectId = newObjId;
6852 } else {
6853 dataSourceObjectId = getDataSourceObjectId(connection, parentId);
6854 }
6855 statement.setLong(21, dataSourceObjectId);
6856
6857 //extension, since this is not really file we just set it to null
6858 statement.setString(22, null);
6859
6860 statement.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
6861 statement.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
6862 statement.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
6863
6864 connection.executeUpdate(statement);
6865
6866 return new VirtualDirectory(this, newObjId, dataSourceObjectId, fileSystemObjectId, directoryName, dirType,
6867 metaType, dirFlag, metaFlags, null, null, null, FileKnown.UNKNOWN,
6868 parentPath);
6869 } catch (SQLException e) {
6870 throw new TskCoreException("Error creating virtual directory '" + directoryName + "'", e);
6871 } finally {
6872 closeResultSet(resultSet);
6873 }
6874 }
6875
6888 public LocalDirectory addLocalDirectory(long parentId, String directoryName) throws TskCoreException {
6889 CaseDbTransaction localTrans = beginTransaction();
6890 try {
6891 LocalDirectory newLD = addLocalDirectory(parentId, directoryName, localTrans);
6892 localTrans.commit();
6893 return newLD;
6894 } catch (TskCoreException ex) {
6895 try {
6896 localTrans.rollback();
6897 } catch (TskCoreException ex2) {
6898 logger.log(Level.SEVERE, String.format("Failed to rollback transaction after exception: %s", ex.getMessage()), ex2);
6899 }
6900 throw ex;
6901 }
6902 }
6903
6921 public LocalDirectory addLocalDirectory(long parentId, String directoryName, CaseDbTransaction transaction) throws TskCoreException {
6922 if (transaction == null) {
6923 throw new TskCoreException("Passed null CaseDbTransaction");
6924 }
6925
6926 ResultSet resultSet = null;
6927 try {
6928 // Get the parent path.
6929 CaseDbConnection connection = transaction.getConnection();
6930 AbstractFile parent = getAbstractFileById(parentId, connection);
6931 String parentPath;
6932 if ((parent == null) || isRootDirectory(parent, transaction)) {
6933 parentPath = "/";
6934 } else {
6935 parentPath = parent.getParentPath() + parent.getName() + "/"; //NON-NLS
6936 }
6937
6938 // Insert a row for the local directory into the tsk_objects table.
6939 long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
6940
6941 // Insert a row for the local directory into the tsk_files table.
6942 // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
6943 // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, sha1, known, mime_type, parent_path, data_source_obj_id, extension, owner_uid, os_account_obj_id)
6944 // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
6945 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
6946 statement.clearParameters();
6947 statement.setLong(1, newObjId);
6948
6949 // The parent of a local directory will never be a file system
6950 statement.setNull(2, java.sql.Types.BIGINT);
6951
6952 // name
6953 statement.setString(3, directoryName);
6954
6955 //type
6956 statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR.getFileType());
6957 statement.setShort(5, (short) 1);
6958
6959 //flags
6961 statement.setShort(6, dirType.getValue());
6963 statement.setShort(7, metaType.getValue());
6964
6965 //allocated
6967 statement.setShort(8, dirFlag.getValue());
6968 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
6969 | TSK_FS_META_FLAG_ENUM.USED.getValue());
6970 statement.setShort(9, metaFlags);
6971
6972 //size
6973 statement.setLong(10, 0);
6974
6975 // nulls for params 11-14
6976 statement.setNull(11, java.sql.Types.BIGINT);
6977 statement.setNull(12, java.sql.Types.BIGINT);
6978 statement.setNull(13, java.sql.Types.BIGINT);
6979 statement.setNull(14, java.sql.Types.BIGINT);
6980
6981 statement.setNull(15, java.sql.Types.VARCHAR); // MD5
6982 statement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
6983 statement.setNull(17, java.sql.Types.VARCHAR); // SHA-1
6984
6985 statement.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
6986 statement.setNull(19, java.sql.Types.VARCHAR); // MIME type
6987
6988 // parent path
6989 statement.setString(20, parentPath);
6990
6991 // data source object id
6992 long dataSourceObjectId = getDataSourceObjectId(connection, parentId);
6993 statement.setLong(21, dataSourceObjectId);
6994
6995 //extension, since this is a directory we just set it to null
6996 statement.setString(22, null);
6997
6998 statement.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
6999 statement.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
7000 statement.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
7001
7002 connection.executeUpdate(statement);
7003
7004 return new LocalDirectory(this, newObjId, dataSourceObjectId, directoryName, dirType,
7005 metaType, dirFlag, metaFlags, null, null, null, FileKnown.UNKNOWN,
7006 parentPath);
7007 } catch (SQLException e) {
7008 throw new TskCoreException("Error creating local directory '" + directoryName + "'", e);
7009 } finally {
7010 closeResultSet(resultSet);
7011 }
7012 }
7013
7033 public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, CaseDbTransaction transaction) throws TskCoreException {
7034 return addLocalFilesDataSource(deviceId, rootDirectoryName, timeZone, null, transaction);
7035 }
7036
7057 public LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, Host host, CaseDbTransaction transaction) throws TskCoreException {
7058
7059 Statement statement = null;
7060 try {
7061 CaseDbConnection connection = transaction.getConnection();
7062
7063 // Insert a row for the root virtual directory of the data source
7064 // into the tsk_objects table.
7065 long newObjId = addObject(0, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
7066
7067 // If no host was supplied, make one
7068 if (host == null) {
7069 host = getHostManager().newHost("LogicalFileSet_" + newObjId + " Host", transaction);
7070 }
7071
7072 // Insert a row for the virtual directory of the data source into
7073 // the data_source_info table.
7074 statement = connection.createStatement();
7075 statement.executeUpdate("INSERT INTO data_source_info (obj_id, device_id, time_zone, host_id) "
7076 + "VALUES(" + newObjId + ", '" + deviceId + "', '" + timeZone + "', " + host.getHostId() + ");");
7077
7078 // Insert a row for the root virtual directory of the data source
7079 // into the tsk_files table. Note that its data source object id is
7080 // its own object id.
7081 // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path,
7082 // dir_type, meta_type, dir_flags, meta_flags, size, ctime, crtime,
7083 // atime, mtime, md5, sha256, sha1, known, mime_type, parent_path, data_source_obj_id, extension, owner_uid, os_account_obj_id)
7084 // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?)
7085 PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
7086 preparedStatement.clearParameters();
7087 preparedStatement.setLong(1, newObjId);
7088 preparedStatement.setNull(2, java.sql.Types.BIGINT);
7089 preparedStatement.setString(3, rootDirectoryName);
7090 preparedStatement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType());
7091 preparedStatement.setShort(5, (short) 1);
7093 preparedStatement.setShort(6, TSK_FS_NAME_TYPE_ENUM.DIR.getValue());
7095 preparedStatement.setShort(7, metaType.getValue());
7097 preparedStatement.setShort(8, dirFlag.getValue());
7098 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
7099 | TSK_FS_META_FLAG_ENUM.USED.getValue());
7100 preparedStatement.setShort(9, metaFlags);
7101 preparedStatement.setLong(10, 0);
7102 preparedStatement.setNull(11, java.sql.Types.BIGINT);
7103 preparedStatement.setNull(12, java.sql.Types.BIGINT);
7104 preparedStatement.setNull(13, java.sql.Types.BIGINT);
7105 preparedStatement.setNull(14, java.sql.Types.BIGINT);
7106 preparedStatement.setNull(15, java.sql.Types.VARCHAR); // MD5
7107 preparedStatement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
7108 preparedStatement.setNull(17, java.sql.Types.VARCHAR); // SHA-1
7109 preparedStatement.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
7110 preparedStatement.setNull(19, java.sql.Types.VARCHAR); // MIME type
7111 String parentPath = "/"; //NON-NLS
7112 preparedStatement.setString(20, parentPath);
7113 preparedStatement.setLong(21, newObjId);
7114 preparedStatement.setString(22, null); //extension, just set it to null
7115 preparedStatement.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
7116 preparedStatement.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
7117 preparedStatement.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
7118
7119
7120 connection.executeUpdate(preparedStatement);
7121
7122 return new LocalFilesDataSource(this, newObjId, newObjId, deviceId, rootDirectoryName, dirType, metaType, dirFlag, metaFlags, timeZone, null, null, null, FileKnown.UNKNOWN, parentPath);
7123
7124 } catch (SQLException ex) {
7125 throw new TskCoreException(String.format("Error creating local files data source with device id %s and directory name %s", deviceId, rootDirectoryName), ex);
7126 } finally {
7127 closeStatement(statement);
7128 }
7129 }
7130
7150 public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths,
7151 String timezone, String md5, String sha1, String sha256,
7152 String deviceId,
7153 CaseDbTransaction transaction) throws TskCoreException {
7154 return addImage(type, sectorSize, size, displayName, imagePaths, timezone, md5, sha1, sha256, deviceId, null, transaction);
7155 }
7156
7177 public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths,
7178 String timezone, String md5, String sha1, String sha256,
7179 String deviceId, Host host,
7180 CaseDbTransaction transaction) throws TskCoreException {
7181
7182 return addImage(type, sectorSize, size, displayName, imagePaths, timezone, md5, sha1, sha256, deviceId, host, null, transaction);
7183 }
7184
7206 @Beta
7207 public Image addImage(TskData.TSK_IMG_TYPE_ENUM type, long sectorSize, long size, String displayName, List<String> imagePaths,
7208 String timezone, String md5, String sha1, String sha256,
7209 String deviceId, Host host, String password,
7210 CaseDbTransaction transaction) throws TskCoreException {
7211 Statement statement = null;
7212 try {
7213 // Insert a row for the Image into the tsk_objects table.
7214 CaseDbConnection connection = transaction.getConnection();
7215 long newObjId = addObject(0, TskData.ObjectType.IMG.getObjectType(), connection);
7216
7217 // Add a row to tsk_image_info
7218 // INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)
7219 PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_INFO);
7220 preparedStatement.clearParameters();
7221 preparedStatement.setLong(1, newObjId);
7222 preparedStatement.setShort(2, (short) type.getValue());
7223 preparedStatement.setLong(3, sectorSize);
7224 preparedStatement.setString(4, timezone);
7225 //prevent negative size
7226 long savedSize = size < 0 ? 0 : size;
7227 preparedStatement.setLong(5, savedSize);
7228 preparedStatement.setString(6, md5);
7229 preparedStatement.setString(7, sha1);
7230 preparedStatement.setString(8, sha256);
7231 preparedStatement.setString(9, displayName);
7232 connection.executeUpdate(preparedStatement);
7233
7234 // If there are paths, add them to tsk_image_names
7235 for (int i = 0; i < imagePaths.size(); i++) {
7236 preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
7237 preparedStatement.clearParameters();
7238 preparedStatement.setLong(1, newObjId);
7239 preparedStatement.setString(2, imagePaths.get(i));
7240 preparedStatement.setLong(3, i);
7241 connection.executeUpdate(preparedStatement);
7242 }
7243
7244 // Create the display name
7245 String name = displayName;
7246 if (name == null || name.isEmpty()) {
7247 if (imagePaths.size() > 0) {
7248 String path = imagePaths.get(0);
7249 name = (new java.io.File(path)).getName();
7250 } else {
7251 name = "";
7252 }
7253 }
7254
7255 // Create a host if needed
7256 if (host == null) {
7257 if (name.isEmpty()) {
7258 host = getHostManager().newHost("Image_" + newObjId + " Host", transaction);
7259 } else {
7260 host = getHostManager().newHost(name + "_" + newObjId + " Host", transaction);
7261 }
7262 }
7263
7264 Map<String, Object> acquisitionToolMap = new HashMap<>();
7265 if (password != null) {
7266 acquisitionToolMap.put(IMAGE_PASSWORD_KEY, password);
7267 }
7268 String acquisitionToolJson = (new Gson()).toJson(acquisitionToolMap);
7269
7270 // Add a row to data_source_info
7271 preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_DATA_SOURCE_INFO);
7272 statement = connection.createStatement();
7273 preparedStatement.setLong(1, newObjId);
7274 preparedStatement.setString(2, deviceId);
7275 preparedStatement.setString(3, timezone);
7276 preparedStatement.setLong(4, new Date().getTime());
7277 preparedStatement.setLong(5, host.getHostId());
7278 preparedStatement.setString(6, acquisitionToolJson);
7279 connection.executeUpdate(preparedStatement);
7280
7281 // Create the new Image object
7282 return new Image(this, newObjId, type.getValue(), deviceId, sectorSize, name,
7283 imagePaths.toArray(new String[imagePaths.size()]), timezone, md5, sha1, sha256, savedSize);
7284 } catch (SQLException ex) {
7285 if (!imagePaths.isEmpty()) {
7286 throw new TskCoreException(String.format("Error adding image with path %s to database", imagePaths.get(0)), ex);
7287 } else {
7288 throw new TskCoreException(String.format("Error adding image with display name %s to database", displayName), ex);
7289 }
7290 } finally {
7291 closeStatement(statement);
7292 }
7293 }
7294
7308 public VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset,
7309 long blockSize, CaseDbTransaction transaction) throws TskCoreException {
7310 try {
7311 // Insert a row for the VolumeSystem into the tsk_objects table.
7312 CaseDbConnection connection = transaction.getConnection();
7313 long newObjId = addObject(parentObjId, TskData.ObjectType.VS.getObjectType(), connection);
7314
7315 // Add a row to tsk_vs_info
7316 // INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size)
7317 PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_INFO);
7318 preparedStatement.clearParameters();
7319 preparedStatement.setLong(1, newObjId);
7320 preparedStatement.setShort(2, (short) type.getVsType());
7321 preparedStatement.setLong(3, imgOffset);
7322 preparedStatement.setLong(4, blockSize);
7323 connection.executeUpdate(preparedStatement);
7324
7325 // Create the new VolumeSystem object
7326 return new VolumeSystem(this, newObjId, "", type.getVsType(), imgOffset, blockSize);
7327 } catch (SQLException ex) {
7328 throw new TskCoreException(String.format("Error creating volume system with parent ID %d and image offset %d",
7329 parentObjId, imgOffset), ex);
7330 }
7331 }
7332
7348 public Volume addVolume(long parentObjId, long addr, long start, long length, String desc,
7349 long flags, CaseDbTransaction transaction) throws TskCoreException {
7350 try {
7351 // Insert a row for the Volume into the tsk_objects table.
7352 CaseDbConnection connection = transaction.getConnection();
7353 long newObjId = addObject(parentObjId, TskData.ObjectType.VOL.getObjectType(), connection);
7354
7355 // Add a row to tsk_vs_parts
7356 // INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags)
7357 PreparedStatement preparedStatement;
7358 if (this.dbType == DbType.POSTGRESQL) {
7359 preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_POSTGRESQL);
7360 } else {
7361 preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_VS_PART_SQLITE);
7362 }
7363 preparedStatement.clearParameters();
7364 preparedStatement.setLong(1, newObjId);
7365 preparedStatement.setLong(2, addr);
7366 preparedStatement.setLong(3, start);
7367 preparedStatement.setLong(4, length);
7368 preparedStatement.setString(5, desc);
7369 preparedStatement.setShort(6, (short) flags);
7370 connection.executeUpdate(preparedStatement);
7371
7372 // Create the new Volume object
7373 return new Volume(this, newObjId, addr, start, length, flags, desc);
7374 } catch (SQLException ex) {
7375 throw new TskCoreException(String.format("Error creating volume with address %d and parent ID %d", addr, parentObjId), ex);
7376 }
7377 }
7378
7390 public Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTransaction transaction) throws TskCoreException {
7391 try {
7392 // Insert a row for the Pool into the tsk_objects table.
7393 CaseDbConnection connection = transaction.getConnection();
7394 long newObjId = addObject(parentObjId, TskData.ObjectType.POOL.getObjectType(), connection);
7395
7396 // Add a row to tsk_pool_info
7397 // INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)
7398 PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_POOL_INFO);
7399 preparedStatement.clearParameters();
7400 preparedStatement.setLong(1, newObjId);
7401 preparedStatement.setShort(2, type.getValue());
7402 connection.executeUpdate(preparedStatement);
7403
7404 // Create the new Pool object
7405 return new Pool(this, newObjId, type.getName(), type.getValue());
7406 } catch (SQLException ex) {
7407 throw new TskCoreException(String.format("Error creating pool with type %d and parent ID %d", type.getValue(), parentObjId), ex);
7408 }
7409 }
7410
7429 public FileSystem addFileSystem(long parentObjId, long imgOffset, TskData.TSK_FS_TYPE_ENUM type, long blockSize, long blockCount,
7430 long rootInum, long firstInum, long lastInum, String displayName,
7431 CaseDbTransaction transaction) throws TskCoreException {
7432 try {
7433 // Insert a row for the FileSystem into the tsk_objects table.
7434 CaseDbConnection connection = transaction.getConnection();
7435 long newObjId = addObject(parentObjId, TskData.ObjectType.FS.getObjectType(), connection);
7436
7437 // Get the data source object ID
7438 long dataSourceId = getDataSourceObjectId(connection, newObjId);
7439
7440 // Add a row to tsk_fs_info
7441 // 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)
7442 PreparedStatement preparedStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FS_INFO);
7443 preparedStatement.clearParameters();
7444 preparedStatement.setLong(1, newObjId);
7445 preparedStatement.setLong(2, dataSourceId);
7446 preparedStatement.setLong(3, imgOffset);
7447 preparedStatement.setInt(4, type.getValue());
7448 preparedStatement.setLong(5, blockSize);
7449 preparedStatement.setLong(6, blockCount);
7450 preparedStatement.setLong(7, rootInum);
7451 preparedStatement.setLong(8, firstInum);
7452 preparedStatement.setLong(9, lastInum);
7453 preparedStatement.setString(10, displayName);
7454 connection.executeUpdate(preparedStatement);
7455
7456 // Create the new FileSystem object
7457 return new FileSystem(this, newObjId, displayName, imgOffset, type, blockSize, blockCount, rootInum,
7458 firstInum, lastInum);
7459 } catch (SQLException ex) {
7460 throw new TskCoreException(String.format("Error creating file system with image offset %d and parent ID %d",
7461 imgOffset, parentObjId), ex);
7462 }
7463 }
7464
7490 public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
7491 String fileName,
7492 long metaAddr, int metaSeq,
7493 TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
7494 TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
7495 long ctime, long crtime, long atime, long mtime,
7496 boolean isFile, Content parent) throws TskCoreException {
7497
7498 CaseDbTransaction transaction = beginTransaction();
7499 try {
7500
7501 FsContent fileSystemFile = addFileSystemFile(dataSourceObjId, fsObjId, fileName,
7502 metaAddr, metaSeq, attrType, attrId, dirFlag, metaFlags, size,
7503 ctime, crtime, atime, mtime, null, null, null, isFile, parent,
7504 OsAccount.NO_OWNER_ID, null,
7505 Collections.emptyList(), transaction);
7506
7507 transaction.commit();
7508 transaction = null;
7509 return fileSystemFile;
7510 } finally {
7511 if (null != transaction) {
7512 try {
7513 transaction.rollback();
7514 } catch (TskCoreException ex2) {
7515 logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
7516 }
7517 }
7518 }
7519 }
7520
7558 public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
7559 String fileName,
7560 long metaAddr, int metaSeq,
7561 TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
7562 TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
7563 long ctime, long crtime, long atime, long mtime,
7564 String md5Hash, String sha256Hash, String mimeType,
7565 boolean isFile, Content parent, String ownerUid,
7566 OsAccount osAccount, List<Attribute> fileAttributes,
7567 CaseDbTransaction transaction) throws TskCoreException {
7568
7569 return addFileSystemFile(dataSourceObjId, fsObjId,
7570 fileName,
7571 metaAddr, metaSeq,
7572 attrType, attrId,
7573 dirFlag, metaFlags, size,
7574 ctime, crtime, atime, mtime,
7575 md5Hash, sha256Hash, null,
7576 mimeType,
7577 isFile, parent, ownerUid,
7578 osAccount, fileAttributes,
7579 transaction);
7580 }
7581
7621 public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
7622 String fileName,
7623 long metaAddr, int metaSeq,
7624 TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
7625 TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
7626 long ctime, long crtime, long atime, long mtime,
7627 String md5Hash, String sha256Hash, String sha1Hash,
7628 String mimeType, boolean isFile,
7629 Content parent, String ownerUid,
7630 OsAccount osAccount, List<Attribute> fileAttributes,
7631 CaseDbTransaction transaction) throws TskCoreException {
7632 return addFileSystemFile(dataSourceObjId, fsObjId,
7633 fileName,
7634 metaAddr, metaSeq,
7635 attrType, attrId,
7636 dirFlag, metaFlags, size,
7637 ctime, crtime, atime, mtime,
7638 md5Hash, sha256Hash, sha1Hash,
7639 mimeType,
7640 isFile, parent, ownerUid,
7641 osAccount, TskData.CollectedStatus.UNKNOWN, fileAttributes,
7642 transaction);
7643 }
7644
7685 public FsContent addFileSystemFile(long dataSourceObjId, long fsObjId,
7686 String fileName,
7687 long metaAddr, int metaSeq,
7688 TSK_FS_ATTR_TYPE_ENUM attrType, int attrId,
7689 TSK_FS_NAME_FLAG_ENUM dirFlag, short metaFlags, long size,
7690 long ctime, long crtime, long atime, long mtime,
7691 String md5Hash, String sha256Hash, String sha1Hash,
7692 String mimeType, boolean isFile,
7693 Content parent, String ownerUid,
7694 OsAccount osAccount, TskData.CollectedStatus collected,
7695 List<Attribute> fileAttributes,
7696 CaseDbTransaction transaction) throws TskCoreException {
7697 TimelineManager timelineManager = getTimelineManager();
7698
7699 Statement queryStatement = null;
7700 String parentPath = "/";
7701 try {
7702 CaseDbConnection connection = transaction.getConnection();
7703
7704 // Insert a row for the local/logical file into the tsk_objects table.
7705 // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
7706 long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
7707
7708 if (parent instanceof AbstractFile) {
7709 AbstractFile parentFile = (AbstractFile) parent;
7710 if (isRootDirectory(parentFile, transaction)) {
7711 parentPath = "/";
7712 } else {
7713 parentPath = parentFile.getParentPath() + parent.getName() + "/"; //NON-NLS
7714 }
7715 } else {
7716 parentPath = "/";
7717 }
7718
7719 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE_SYSTEM_FILE);
7720 statement.clearParameters();
7721 statement.setLong(1, objectId); // obj_is
7722 statement.setLong(2, fsObjId); // fs_obj_id
7723 statement.setLong(3, dataSourceObjId); // data_source_obj_id
7724 statement.setShort(4, (short) attrType.getValue()); // attr_type
7725 statement.setInt(5, attrId); // attr_id
7726 statement.setString(6, fileName); // name
7727 statement.setLong(7, metaAddr); // meta_addr
7728 statement.setInt(8, metaSeq); // meta_addr
7729 statement.setShort(9, TskData.TSK_DB_FILES_TYPE_ENUM.FS.getFileType()); //type
7730 statement.setShort(10, (short) 1); // has_path
7732 statement.setShort(11, dirType.getValue()); // dir_type
7734 statement.setShort(12, metaType.getValue()); // meta_type
7735 statement.setShort(13, dirFlag.getValue()); // dir_flags
7736 statement.setShort(14, metaFlags); // meta_flags
7737 statement.setLong(15, size < 0 ? 0 : size);
7738 statement.setLong(16, ctime);
7739 statement.setLong(17, crtime);
7740 statement.setLong(18, atime);
7741 statement.setLong(19, mtime);
7742 statement.setString(20, md5Hash);
7743 statement.setString(21, sha256Hash);
7744 statement.setString(22, sha1Hash);
7745 statement.setString(23, mimeType);
7746 statement.setString(24, parentPath);
7747 final String extension = extractExtension(fileName);
7748 statement.setString(25, extension);
7749 statement.setString(26, ownerUid);
7750 if (null != osAccount) {
7751 statement.setLong(27, osAccount.getId());
7752 } else {
7753 statement.setNull(27, java.sql.Types.BIGINT); // osAccountObjId
7754 }
7755 statement.setLong(28, collected.getType());
7756
7757 connection.executeUpdate(statement);
7758
7759 Long osAccountId = (osAccount != null) ? osAccount.getId() : null;
7760 DerivedFile derivedFile = new DerivedFile(this, objectId, dataSourceObjId, fsObjId, fileName, dirType, metaType, dirFlag, metaFlags,
7761 size, ctime, crtime, atime, mtime, md5Hash, sha256Hash, sha1Hash, null, parentPath, null, parent.getId(), mimeType, null, extension, ownerUid, osAccountId);
7762
7763 if (!timelineEventsDisabled.get()) {
7764 timelineManager.addEventsForNewFile(derivedFile, connection);
7765 }
7766
7767 for (Attribute fileAttribute : fileAttributes) {
7768 fileAttribute.setAttributeParentId(objectId);
7769 fileAttribute.setCaseDatabase(this);
7770 addFileAttribute(fileAttribute, connection);
7771 }
7772
7773 if (osAccount != null) {
7774 osAccountManager.newOsAccountInstance(osAccount.getId(), dataSourceObjId, OsAccountInstance.OsAccountInstanceType.ACCESSED, connection);
7775 }
7776
7777 return new org.sleuthkit.datamodel.File(this, objectId, dataSourceObjId, fsObjId,
7778 attrType, attrId, fileName, metaAddr, metaSeq,
7779 dirType, metaType, dirFlag, metaFlags,
7780 size, ctime, crtime, atime, mtime,
7781 (short) 0, 0, 0, md5Hash, sha256Hash, sha1Hash, null, parentPath, mimeType,
7782 extension, ownerUid, osAccountId, collected, fileAttributes);
7783
7784 } catch (SQLException ex) {
7785 throw new TskCoreException(String.format("Failed to INSERT file system file %s (%s) with parent id %d in tsk_files table", fileName, parentPath, parent.getId()), ex);
7786 } finally {
7787 closeStatement(queryStatement);
7788 }
7789 }
7790
7799 public List<VirtualDirectory> getVirtualDirectoryRoots() throws TskCoreException {
7800 CaseDbConnection connection = null;
7801 Statement s = null;
7802 ResultSet rs = null;
7804 try {
7805 connection = connections.getConnection();
7806 s = connection.createStatement();
7807 rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE" //NON-NLS
7808 + " type = " + TskData.TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
7809 + " AND obj_id = data_source_obj_id"
7810 + " ORDER BY dir_type, LOWER(name)"); //NON-NLS
7811 List<VirtualDirectory> virtDirRootIds = new ArrayList<VirtualDirectory>();
7812 while (rs.next()) {
7813 virtDirRootIds.add(virtualDirectory(rs, connection));
7814 }
7815 return virtDirRootIds;
7816 } catch (SQLException ex) {
7817 throw new TskCoreException("Error getting local files virtual folder id", ex);
7818 } finally {
7819 closeResultSet(rs);
7820 closeStatement(s);
7821 closeConnection(connection);
7823 }
7824 }
7825
7838 public final List<LayoutFile> addLayoutFiles(Content parent, List<TskFileRange> fileRanges) throws TskCoreException {
7839 assert (null != fileRanges);
7840 if (null == fileRanges) {
7841 throw new TskCoreException("TskFileRange object is null");
7842 }
7843
7844 assert (null != parent);
7845 if (null == parent) {
7846 throw new TskCoreException("Conent is null");
7847 }
7848
7849 String parentPath;
7850 if (parent instanceof AbstractFile) {
7851 parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + '/'; //NON-NLS
7852 } else {
7853 parentPath = "/";
7854 }
7855
7856 CaseDbTransaction transaction = null;
7857 Statement statement = null;
7858 ResultSet resultSet = null;
7859
7860 try {
7861 transaction = beginTransaction();
7862 CaseDbConnection connection = transaction.getConnection();
7863
7864 // If the parent is part of a file system, grab its file system ID
7865 Long fileSystemObjectId;
7866 if (0 != parent.getId()) {
7867 fileSystemObjectId = this.getFileSystemId(parent.getId(), connection);
7868 if (fileSystemObjectId == -1) {
7869 fileSystemObjectId = null;
7870 }
7871 } else {
7872 fileSystemObjectId = null;
7873 }
7874
7875 List<LayoutFile> fileRangeLayoutFiles = new ArrayList<>();
7876 for (TskFileRange fileRange : fileRanges) {
7877 /*
7878 * Insert a row for the Tsk file range into the tsk_objects
7879 * table: INSERT INTO tsk_objects (par_obj_id, type) VALUES (?,
7880 * ?)
7881 */
7882 long fileRangeId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
7883 long end_byte_in_parent = fileRange.getByteStart() + fileRange.getByteLen() - 1;
7884 /*
7885 * Insert a row for the Tsk file range into the tsk_files table:
7886 * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type,
7887 * has_path, dir_type, meta_type, dir_flags, meta_flags, size,
7888 * ctime, crtime, atime, mtime, md5, sha256, sha1, known, mime_type,
7889 * parent_path, data_source_obj_id,extension, owner_uid,
7890 * os_account_obj_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
7891 * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?)
7892 */
7893 PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
7894 prepStmt.clearParameters();
7895 prepStmt.setLong(1, fileRangeId); // obj_id from tsk_objects
7896 if (fileSystemObjectId != null) {
7897 prepStmt.setLong(2, fileSystemObjectId);// fs_obj_id
7898 } else {
7899 prepStmt.setNull(2, java.sql.Types.BIGINT);
7900 }
7901 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]
7902 prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()); // type
7903 prepStmt.setNull(5, java.sql.Types.BIGINT); // has_path
7904 prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
7905 prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
7906 prepStmt.setShort(8, TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()); // dir_flags
7907 prepStmt.setShort(9, TSK_FS_META_FLAG_ENUM.UNALLOC.getValue()); // nmeta_flags
7908 prepStmt.setLong(10, fileRange.getByteLen()); // size
7909 prepStmt.setNull(11, java.sql.Types.BIGINT); // ctime
7910 prepStmt.setNull(12, java.sql.Types.BIGINT); // crtime
7911 prepStmt.setNull(13, java.sql.Types.BIGINT); // atime
7912 prepStmt.setNull(14, java.sql.Types.BIGINT); // mtime
7913 prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
7914 prepStmt.setNull(16, java.sql.Types.VARCHAR); // SHA-256
7915 prepStmt.setNull(17, java.sql.Types.VARCHAR); // SHA-1
7916
7917 prepStmt.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
7918 prepStmt.setNull(19, java.sql.Types.VARCHAR); // MIME type
7919 prepStmt.setString(20, parentPath); // parent path
7920 prepStmt.setLong(21, parent.getId()); // data_source_obj_id
7921
7922 //extension, since this is not a FS file we just set it to null
7923 prepStmt.setString(22, null);
7924
7925 prepStmt.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
7926 prepStmt.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
7927 prepStmt.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
7928
7929 connection.executeUpdate(prepStmt);
7930
7931 /*
7932 * Insert a row in the tsk_layout_file table for each chunk of
7933 * the carved file. INSERT INTO tsk_file_layout (obj_id,
7934 * byte_start, byte_len, sequence) VALUES (?, ?, ?, ?)
7935 */
7936 prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
7937 prepStmt.clearParameters();
7938 prepStmt.setLong(1, fileRangeId); // obj_id
7939 prepStmt.setLong(2, fileRange.getByteStart()); // byte_start
7940 prepStmt.setLong(3, fileRange.getByteLen()); // byte_len
7941 prepStmt.setLong(4, fileRange.getSequence()); // sequence
7942 connection.executeUpdate(prepStmt);
7943
7944 /*
7945 * Create a layout file representation of the carved file.
7946 */
7947 fileRangeLayoutFiles.add(new LayoutFile(this,
7948 fileRangeId,
7949 parent.getId(),
7950 fileSystemObjectId,
7951 Long.toString(fileRange.getSequence()),
7956 TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
7957 fileRange.getByteLen(),
7958 0L, 0L, 0L, 0L,
7959 null, null, null,
7961 parent.getUniquePath(),
7962 null,
7963 OsAccount.NO_OWNER_ID,
7964 OsAccount.NO_ACCOUNT));
7965 }
7966
7967 transaction.commit();
7968 transaction = null;
7969 return fileRangeLayoutFiles;
7970
7971 } catch (SQLException ex) {
7972 throw new TskCoreException("Failed to add layout files to case database", ex);
7973 } finally {
7974 closeResultSet(resultSet);
7975 closeStatement(statement);
7976
7977 if (null != transaction) {
7978 try {
7979 transaction.rollback();
7980 } catch (TskCoreException ex2) {
7981 logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
7982 }
7983 }
7984 }
7985 }
7986
7993 private class CarvedFileDirInfo {
7994
7995 final VirtualDirectory currentFolder;
7996 AtomicInteger count;
7997
7998 CarvedFileDirInfo(VirtualDirectory currentFolder) {
7999 this.currentFolder = currentFolder;
8000 count = new AtomicInteger(0);
8001 }
8002
8003 CarvedFileDirInfo(VirtualDirectory currentFolder, int count) {
8004 this.currentFolder = currentFolder;
8005 this.count = new AtomicInteger(count);
8006 }
8007
8014 boolean isFull() {
8015 return count.get() >= MAX_CARVED_FILES_PER_FOLDER;
8016 }
8017
8021 void incrementFileCounter() {
8022 count.incrementAndGet();
8023 }
8024 }
8025
8035 private CarvedFileDirInfo getMostRecentCarvedDirInfo(VirtualDirectory carvedFilesBaseDir) throws TskCoreException {
8036 VirtualDirectory mostRecentDir = null;
8037 for (Content child : carvedFilesBaseDir.getChildren()) {
8038 if (isValidCarvedFileSubfolder(child)) {
8039 if (mostRecentDir == null
8040 || (mostRecentDir.getId() < child.getId())) {
8041 mostRecentDir = (VirtualDirectory) child;
8042 }
8043 }
8044 }
8045
8046 if (mostRecentDir != null) {
8047 return new CarvedFileDirInfo(mostRecentDir, mostRecentDir.getChildrenCount());
8048 }
8049 return null;
8050 }
8051
8060 private boolean isValidCarvedFileSubfolder(Content subfolder) {
8061 if (!(subfolder instanceof VirtualDirectory)) {
8062 return false;
8063 }
8064 return subfolder.getName().matches("^[0-9]+$");
8065 }
8066
8080 private CarvedFileDirInfo createCarvedFilesSubfolder(Content carvedFilesBaseDir, CarvedFileDirInfo currentSubfolderInfo) throws TskCoreException {
8081 int nextIndex = 1;
8082 if (currentSubfolderInfo != null) {
8083 try {
8084 int currentIndex = Integer.parseInt(currentSubfolderInfo.currentFolder.getName());
8085 nextIndex = currentIndex + 1;
8086 } catch (NumberFormatException ex) {
8087 throw new TskCoreException("Unexpected name format for carved files subdirectory with ID: " + currentSubfolderInfo.currentFolder.getId() + " (" + currentSubfolderInfo.currentFolder.getName() + ")", ex);
8088 }
8089 }
8090
8091 VirtualDirectory carvedFilesSubdir = addVirtualDirectory(carvedFilesBaseDir.getId(), Integer.toString(nextIndex));
8092 return new CarvedFileDirInfo(carvedFilesSubdir);
8093 }
8094
8106 public final List<LayoutFile> addCarvedFiles(CarvingResult carvingResult) throws TskCoreException {
8107 assert (null != carvingResult);
8108 if (null == carvingResult) {
8109 throw new TskCoreException("Carving is null");
8110 }
8111 assert (null != carvingResult.getParent());
8112 if (null == carvingResult.getParent()) {
8113 throw new TskCoreException("Carving result has null parent");
8114 }
8115 assert (null != carvingResult.getCarvedFiles());
8116 if (null == carvingResult.getCarvedFiles()) {
8117 throw new TskCoreException("Carving result has null carved files");
8118 }
8119 CaseDbTransaction transaction = null;
8120 Statement statement = null;
8121 ResultSet resultSet = null;
8122 try {
8123
8124 /*
8125 * Carved files are "re-parented" as children of the $CarvedFiles
8126 * virtual directory of the root file system, volume, or image
8127 * ancestor of the carved files parent, but if no such ancestor is
8128 * found, then the parent specified in the carving result is used.
8129 */
8130 Content root = carvingResult.getParent();
8131 while (null != root) {
8132 if (root instanceof FileSystem || root instanceof Volume || root instanceof Image) {
8133 break;
8134 }
8135 root = root.getParent();
8136 }
8137 if (null == root) {
8138 root = carvingResult.getParent();
8139 }
8140
8141 /*
8142 * Get or create the $CarvedFiles virtual directory for the root
8143 * ancestor.
8144 */
8145 CarvedFileDirInfo carvedFilesDirInfo = null;
8146 synchronized (carvedFileDirsLock) {
8147 // Get the subfolder currently in use (if there is one)
8148 carvedFilesDirInfo = rootIdsToCarvedFileDirs.get(root.getId());
8149 if (carvedFilesDirInfo != null) {
8150 carvedFilesDirInfo.incrementFileCounter();
8151
8152 // If the current folder is full, create a new one.
8153 if (carvedFilesDirInfo.isFull()) {
8154 carvedFilesDirInfo = createCarvedFilesSubfolder(carvedFilesDirInfo.currentFolder.getParent(), carvedFilesDirInfo);
8155 }
8156 }
8157
8158 if (null == carvedFilesDirInfo) {
8159 List<Content> rootChildren;
8160 if (root instanceof FileSystem) {
8161 rootChildren = ((FileSystem) root).getRootDirectory().getChildren();
8162 } else {
8163 rootChildren = root.getChildren();
8164 }
8165 for (Content child : rootChildren) {
8166 if (child instanceof VirtualDirectory && child.getName().equals(VirtualDirectory.NAME_CARVED)) {
8167
8168 VirtualDirectory baseDir = (VirtualDirectory) child;
8169
8170 // Get the most recent subfolder in the carved files folder.
8171 carvedFilesDirInfo = getMostRecentCarvedDirInfo(baseDir);
8172
8173 // If there are no subfolders, create one.
8174 if (carvedFilesDirInfo == null) {
8175 carvedFilesDirInfo = createCarvedFilesSubfolder(baseDir, null);
8176 }
8177
8178 // If there are already too many files in the subfolder, create a new one.
8179 if (carvedFilesDirInfo.isFull()) {
8180 carvedFilesDirInfo = createCarvedFilesSubfolder(baseDir, carvedFilesDirInfo);
8181 }
8182
8183 rootIdsToCarvedFileDirs.put(root.getId(), carvedFilesDirInfo);
8184 break;
8185 }
8186 }
8187 if (carvedFilesDirInfo == null) {
8188 // If we get here, we didn't have a carved files base folder in the case, so we need to make that and
8189 // the first subfolder.
8190
8191 long parId = root.getId();
8192 // $CarvedFiles should be a child of the root directory, not the file system
8193 if (root instanceof FileSystem) {
8194 Content rootDir = ((FileSystem) root).getRootDirectory();
8195 parId = rootDir.getId();
8196 }
8198 carvedFilesDirInfo = createCarvedFilesSubfolder(carvedFilesBaseDir, null);
8199 rootIdsToCarvedFileDirs.put(root.getId(), carvedFilesDirInfo);
8200 }
8201 }
8202 }
8203
8204 /*
8205 * Add the carved files to the database as children of the
8206 * $CarvedFile directory of the root ancestor.
8207 */
8208 VirtualDirectory carvedFilesBaseDir = (VirtualDirectory) carvedFilesDirInfo.currentFolder.getParent();
8209 transaction = beginTransaction();
8210 CaseDbConnection connection = transaction.getConnection();
8211 String parentPath = getFileParentPath(carvedFilesDirInfo.currentFolder.getId(), connection) + carvedFilesDirInfo.currentFolder.getName() + "/";
8212 List<LayoutFile> carvedFiles = new ArrayList<>();
8213 for (CarvingResult.CarvedFile carvedFile : carvingResult.getCarvedFiles()) {
8214
8215 /*
8216 * Check if we need to change to a new subfolder.
8217 */
8218 VirtualDirectory carvedFilesDir = carvedFilesDirInfo.currentFolder;
8219 if (carvedFilesDirInfo.isFull()) {
8220 // To prevent deadlocks involving the case write lock and the carvedFileDirsLock,
8221 // commit the current transaction and then start a new one
8222 // after switching to the new folder.
8223 transaction.commit();
8224
8225 synchronized (carvedFileDirsLock) {
8226 // Get the current copy from the map - another thread may have just created a new folder.
8227 carvedFilesDirInfo = rootIdsToCarvedFileDirs.get(root.getId());
8228 if (carvedFilesDirInfo.isFull()) {
8229 carvedFilesDirInfo = createCarvedFilesSubfolder(carvedFilesBaseDir, carvedFilesDirInfo);
8230 rootIdsToCarvedFileDirs.put(root.getId(), carvedFilesDirInfo);
8231 carvedFilesDir = carvedFilesDirInfo.currentFolder;
8232 }
8233 }
8234
8235 // Start a new transaction.
8236 transaction = beginTransaction();
8237 connection = transaction.getConnection();
8238 parentPath = getFileParentPath(carvedFilesDir.getId(), connection) + carvedFilesDir.getName() + "/";
8239
8240 }
8241 carvedFilesDirInfo.incrementFileCounter();
8242
8243 /*
8244 * Insert a row for the carved file into the tsk_objects table:
8245 * INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
8246 */
8247 long carvedFileId = addObject(carvedFilesDir.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
8248
8249
8250 /*
8251 * Insert a row for the carved file into the tsk_files table:
8252 * INSERT INTO tsk_files (obj_id, fs_obj_id, name, type,
8253 * has_path, dir_type, meta_type, dir_flags, meta_flags, size,
8254 * ctime, crtime, atime, mtime, md5, sha256, sha1, known, mime_type,
8255 * parent_path, data_source_obj_id,extenion, owner_uid,
8256 * os_account_obj_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,
8257 * ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
8258 */
8259 PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
8260 prepStmt.clearParameters();
8261 prepStmt.setLong(1, carvedFileId); // obj_id
8262 Long fileSystemObjectId;
8263 if (root instanceof FileSystem) {
8264 prepStmt.setLong(2, root.getId()); // fs_obj_id
8265 fileSystemObjectId = root.getId();
8266 } else {
8267 prepStmt.setNull(2, java.sql.Types.BIGINT); // fs_obj_id
8268 fileSystemObjectId = null;
8269 }
8270 prepStmt.setString(3, carvedFile.getName()); // name
8271 prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()); // type
8272 prepStmt.setShort(5, (short) 1); // has_path
8273 prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
8274 prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
8275 prepStmt.setShort(8, TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue()); // dir_flags
8276 prepStmt.setShort(9, TSK_FS_META_FLAG_ENUM.UNALLOC.getValue()); // nmeta_flags
8277 prepStmt.setLong(10, carvedFile.getSizeInBytes()); // size
8278 prepStmt.setNull(11, java.sql.Types.BIGINT); // ctime
8279 prepStmt.setNull(12, java.sql.Types.BIGINT); // crtime
8280 prepStmt.setNull(13, java.sql.Types.BIGINT); // atime
8281 prepStmt.setNull(14, java.sql.Types.BIGINT); // mtime
8282 prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
8283 prepStmt.setNull(16, java.sql.Types.VARCHAR); // SHA-256
8284 prepStmt.setNull(17, java.sql.Types.VARCHAR); // SHA-1
8285
8286 prepStmt.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
8287 prepStmt.setNull(19, java.sql.Types.VARCHAR); // MIME type
8288 prepStmt.setString(20, parentPath); // parent path
8289 prepStmt.setLong(21, carvedFilesDir.getDataSourceObjectId()); // data_source_obj_id
8290 prepStmt.setString(22, extractExtension(carvedFile.getName())); //extension
8291
8292 prepStmt.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
8293 prepStmt.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
8294 prepStmt.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
8295
8296 connection.executeUpdate(prepStmt);
8297
8298 /*
8299 * Insert a row in the tsk_layout_file table for each chunk of
8300 * the carved file. INSERT INTO tsk_file_layout (obj_id,
8301 * byte_start, byte_len, sequence) VALUES (?, ?, ?, ?)
8302 */
8303 prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
8304 for (TskFileRange tskFileRange : carvedFile.getLayoutInParent()) {
8305 prepStmt.clearParameters();
8306 prepStmt.setLong(1, carvedFileId); // obj_id
8307 prepStmt.setLong(2, tskFileRange.getByteStart()); // byte_start
8308 prepStmt.setLong(3, tskFileRange.getByteLen()); // byte_len
8309 prepStmt.setLong(4, tskFileRange.getSequence()); // sequence
8310 connection.executeUpdate(prepStmt);
8311 }
8312
8313 /*
8314 * Create a layout file representation of the carved file.
8315 */
8316 carvedFiles.add(new LayoutFile(this,
8317 carvedFileId,
8318 carvedFilesDir.getDataSourceObjectId(),
8319 fileSystemObjectId,
8320 carvedFile.getName(),
8325 TSK_FS_META_FLAG_ENUM.UNALLOC.getValue(),
8326 carvedFile.getSizeInBytes(),
8327 0L, 0L, 0L, 0L,
8328 null, null, null,
8330 parentPath,
8331 null,
8332 OsAccount.NO_OWNER_ID,
8333 OsAccount.NO_ACCOUNT));
8334 }
8335
8336 transaction.commit();
8337 transaction = null;
8338 return carvedFiles;
8339
8340 } catch (SQLException ex) {
8341 throw new TskCoreException("Failed to add carved files to case database", ex);
8342 } finally {
8343 closeResultSet(resultSet);
8344 closeStatement(statement);
8345
8346 if (null != transaction) {
8347 try {
8348 transaction.rollback();
8349 } catch (TskCoreException ex2) {
8350 logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
8351 }
8352 }
8353 }
8354 }
8355
8386 public DerivedFile addDerivedFile(String fileName, String localPath,
8387 long size, long ctime, long crtime, long atime, long mtime,
8388 boolean isFile, Content parentObj,
8389 String rederiveDetails, String toolName, String toolVersion,
8390 String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
8391 CaseDbTransaction transaction = beginTransaction();
8392 try {
8393 DerivedFile df = addDerivedFile(fileName, localPath,
8394 size, ctime, crtime, atime, mtime,
8395 isFile, parentObj,
8396 rederiveDetails, toolName, toolVersion,
8397 otherDetails, encodingType, transaction);
8398 transaction.commit();
8399 return df;
8400 } catch (TskCoreException ex) {
8401 transaction.rollback();
8402 throw ex;
8403 }
8404 }
8405
8406 public DerivedFile addDerivedFile(String fileName, String localPath,
8407 long size, long ctime, long crtime, long atime, long mtime,
8408 boolean isFile, Content parentObj,
8409 String rederiveDetails, String toolName, String toolVersion,
8410 String otherDetails, TskData.EncodingType encodingType, CaseDbTransaction transaction) throws TskCoreException {
8411 // Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
8412 localPath = localPath.replaceAll("^[/\\\\]+", "");
8413
8414 TimelineManager timelineManager = getTimelineManager();
8415
8416 CaseDbConnection connection = transaction.getConnection();
8417 try {
8418 final long parentId = parentObj.getId();
8419 String parentPath = "";
8420 if (parentObj instanceof BlackboardArtifact) {
8421 parentPath = parentObj.getUniquePath() + '/' + parentObj.getName() + '/';
8422 } else if (parentObj instanceof AbstractFile) {
8423 parentPath = ((AbstractFile) parentObj).getParentPath() + parentObj.getName() + '/'; //NON-NLS
8424 }
8425
8426 // Insert a row for the derived file into the tsk_objects table.
8427 // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
8428 long newObjId = addObject(parentId, TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
8429
8430 // Insert a row for the virtual directory into the tsk_files table.
8431 // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
8432 // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, known, mime_type,
8433 // parent_path, data_source_obj_id, extension)
8434 // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?)
8435 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
8436 statement.clearParameters();
8437 statement.setLong(1, newObjId);
8438
8439 // If the parentFile is part of a file system, use its file system object ID.
8440 Long fsObjId = this.getFileSystemId(parentId, connection);
8441 if (fsObjId != -1) {
8442 statement.setLong(2, fsObjId);
8443 } else {
8444 fsObjId = null;
8445 statement.setNull(2, java.sql.Types.BIGINT);
8446 }
8447 statement.setString(3, fileName);
8448
8449 //type, has_path
8450 statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType());
8451 statement.setShort(5, (short) 1);
8452
8453 //flags
8455 statement.setShort(6, dirType.getValue());
8457 statement.setShort(7, metaType.getValue());
8458
8459 //note: using alloc under assumption that derived files derive from alloc files
8461 statement.setShort(8, dirFlag.getValue());
8462 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
8463 | TSK_FS_META_FLAG_ENUM.USED.getValue());
8464 statement.setShort(9, metaFlags);
8465
8466 //size
8467 //prevent negative size
8468 long savedSize = size < 0 ? 0 : size;
8469 statement.setLong(10, savedSize);
8470
8471 //mactimes
8472 //long ctime, long crtime, long atime, long mtime,
8473 statement.setLong(11, ctime);
8474 statement.setLong(12, crtime);
8475 statement.setLong(13, atime);
8476 statement.setLong(14, mtime);
8477
8478 statement.setNull(15, java.sql.Types.VARCHAR); // MD5
8479 statement.setNull(16, java.sql.Types.VARCHAR); // SHA-256
8480 statement.setNull(17, java.sql.Types.VARCHAR); // SHA-1
8481
8482 statement.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
8483 statement.setNull(19, java.sql.Types.VARCHAR); // MIME type
8484
8485 //parent path
8486 statement.setString(20, parentPath);
8487
8488 // root data source object id
8489 long dataSourceObjId = getDataSourceObjectId(connection, parentObj);
8490 statement.setLong(21, dataSourceObjId);
8491 final String extension = extractExtension(fileName);
8492 //extension
8493 statement.setString(22, extension);
8494
8495 statement.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
8496 statement.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
8497 statement.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
8498
8499 connection.executeUpdate(statement);
8500
8501 //add localPath
8502 addFilePath(connection, newObjId, localPath, encodingType);
8503
8504 DerivedFile derivedFile = new DerivedFile(this, newObjId, dataSourceObjId, fsObjId, fileName, dirType, metaType, dirFlag, metaFlags,
8505 savedSize, ctime, crtime, atime, mtime, null, null, null, null, parentPath, localPath, parentId, null, encodingType, extension, OsAccount.NO_OWNER_ID, OsAccount.NO_ACCOUNT);
8506
8507 if (!timelineEventsDisabled.get()) {
8508 timelineManager.addEventsForNewFile(derivedFile, connection);
8509 }
8510
8511 //TODO add derived method to tsk_files_derived and tsk_files_derived_method
8512 return derivedFile;
8513 } catch (SQLException ex) {
8514 throw new TskCoreException("Failed to add derived file to case database", ex);
8515 }
8516 }
8517
8548 public DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath,
8549 long size, long ctime, long crtime, long atime, long mtime,
8550 boolean isFile, String mimeType,
8551 String rederiveDetails, String toolName, String toolVersion,
8552 String otherDetails, TskData.EncodingType encodingType) throws TskCoreException {
8553
8554 CaseDbTransaction trans = null;
8555 try {
8556 Content parentObj = derivedFile.getParent();
8557
8558 trans = beginTransaction();
8559 DerivedFile updatedFile = updateDerivedFile(derivedFile, localPath,
8560 size, ctime, crtime, atime, mtime,
8561 isFile, mimeType,
8562 rederiveDetails, toolName, toolVersion,
8563 otherDetails, encodingType, parentObj, trans);
8564 trans.commit();
8565 return updatedFile;
8566 } catch (TskCoreException ex) {
8567 if (trans != null) {
8568 trans.rollback();
8569 }
8570 throw ex;
8571 }
8572 }
8573
8574 public DerivedFile updateDerivedFile(DerivedFile derivedFile, String localPath,
8575 long size, long ctime, long crtime, long atime, long mtime,
8576 boolean isFile, String mimeType,
8577 String rederiveDetails, String toolName, String toolVersion,
8578 String otherDetails, TskData.EncodingType encodingType,
8579 Content parentObj, CaseDbTransaction trans) throws TskCoreException {
8580
8581 // Strip off any leading slashes from the local path (leading slashes indicate absolute paths)
8582 localPath = localPath.replaceAll("^[/\\\\]+", "");
8583
8584 ResultSet rs = null;
8585 try {
8586 final long parentId = parentObj.getId();
8587 String parentPath = "";
8588 if (parentObj instanceof BlackboardArtifact) {
8589 parentPath = parentObj.getUniquePath() + '/' + parentObj.getName() + '/';
8590 } else if (parentObj instanceof AbstractFile) {
8591 parentPath = ((AbstractFile) parentObj).getParentPath() + parentObj.getName() + '/'; //NON-NLS
8592 }
8593 // UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, "
8594 // + "size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? WHERE obj_id = ?"), //NON-NLS
8595 PreparedStatement statement = trans.getConnection().getPreparedStatement(PREPARED_STATEMENT.UPDATE_DERIVED_FILE);
8596 statement.clearParameters();
8597
8598 //type
8599 statement.setShort(1, TskData.TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType());
8600
8601 //flags
8603 statement.setShort(2, dirType.getValue());
8605 statement.setShort(3, metaType.getValue());
8606
8607 //note: using alloc under assumption that derived files derive from alloc files
8609 statement.setShort(4, dirFlag.getValue());
8610 final short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue()
8611 | TSK_FS_META_FLAG_ENUM.USED.getValue());
8612 statement.setShort(5, metaFlags);
8613
8614 //size
8615 //prevent negative size
8616 long savedSize = size < 0 ? 0 : size;
8617 statement.setLong(6, savedSize);
8618
8619 //mactimes
8620 //long ctime, long crtime, long atime, long mtime,
8621 statement.setLong(7, ctime);
8622 statement.setLong(8, crtime);
8623 statement.setLong(9, atime);
8624 statement.setLong(10, mtime);
8625 statement.setString(11, mimeType);
8626 statement.setString(12, String.valueOf(derivedFile.getId()));
8627 trans.getConnection().executeUpdate(statement);
8628
8629 //add localPath
8630 updateFilePath(trans.getConnection(), derivedFile.getId(), localPath, encodingType);
8631
8632 long dataSourceObjId = getDataSourceObjectId(trans.getConnection(), parentObj);
8633 Long fileSystemObjId = derivedFile.getFileSystemObjectId().orElse(null);
8634 final String extension = extractExtension(derivedFile.getName());
8635 return new DerivedFile(this, derivedFile.getId(), dataSourceObjId, fileSystemObjId, derivedFile.getName(), dirType, metaType, dirFlag, metaFlags,
8636 savedSize, ctime, crtime, atime, mtime, null, null, null, null, parentPath, localPath, parentId, null, encodingType, extension,
8637 derivedFile.getOwnerUid().orElse(null), derivedFile.getOsAccountObjectId().orElse(null));
8638 } catch (SQLException ex) {
8639 throw new TskCoreException("Failed to add derived file to case database", ex);
8640 } finally {
8641 closeResultSet(rs);
8642 }
8643 }
8644
8664 public LocalFile addLocalFile(String fileName, String localPath,
8665 long size, long ctime, long crtime, long atime, long mtime,
8666 boolean isFile, TskData.EncodingType encodingType,
8667 AbstractFile parent) throws TskCoreException {
8668
8669 CaseDbTransaction localTrans = beginTransaction();
8670 try {
8671 LocalFile created = addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile, encodingType, parent, localTrans);
8672 localTrans.commit();
8673 localTrans = null;
8674 return created;
8675 } finally {
8676 if (null != localTrans) {
8677 try {
8678 localTrans.rollback();
8679 } catch (TskCoreException ex2) {
8680 logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
8681 }
8682 }
8683 }
8684 }
8685
8710 public LocalFile addLocalFile(String fileName, String localPath,
8711 long size, long ctime, long crtime, long atime, long mtime,
8712 boolean isFile, TskData.EncodingType encodingType,
8713 Content parent, CaseDbTransaction transaction) throws TskCoreException {
8714
8715 return addLocalFile(fileName, localPath,
8716 size, ctime, crtime, atime, mtime,
8717 null, null, null,
8718 isFile, encodingType,
8719 parent, transaction);
8720 }
8721
8750 public LocalFile addLocalFile(String fileName, String localPath,
8751 long size, long ctime, long crtime, long atime, long mtime,
8752 String md5, String sha256, FileKnown known, String mimeType,
8753 boolean isFile, TskData.EncodingType encodingType,
8754 Content parent, CaseDbTransaction transaction) throws TskCoreException {
8755
8756 return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime,
8757 md5, sha256, known, mimeType, isFile, encodingType,
8758 OsAccount.NO_ACCOUNT, OsAccount.NO_OWNER_ID, parent, transaction);
8759
8760 }
8761
8792 public LocalFile addLocalFile(String fileName, String localPath,
8793 long size, long ctime, long crtime, long atime, long mtime,
8794 String md5, String sha256, FileKnown known, String mimeType,
8795 boolean isFile, TskData.EncodingType encodingType, Long osAccountId, String ownerAccount,
8796 Content parent, CaseDbTransaction transaction) throws TskCoreException {
8797
8798 return addLocalFile(fileName, localPath,
8799 size, ctime, crtime, atime, mtime,
8800 md5, sha256, null, known, mimeType,
8801 isFile, encodingType, osAccountId, ownerAccount,
8802 parent, transaction);
8803 }
8804
8805
8838 public LocalFile addLocalFile(String fileName, String localPath,
8839 long size, long ctime, long crtime, long atime, long mtime,
8840 String md5, String sha256, String sha1Hash, FileKnown known, String mimeType,
8841 boolean isFile, TskData.EncodingType encodingType, Long osAccountId, String ownerAccount,
8842 Content parent, CaseDbTransaction transaction) throws TskCoreException {
8843 CaseDbConnection connection = transaction.getConnection();
8844 Statement queryStatement = null;
8845 try {
8846
8847 // Insert a row for the local/logical file into the tsk_objects table.
8848 // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
8849 long objectId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
8850
8851 // Insert a row for the local/logical file into the tsk_files table.
8852 // INSERT INTO tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type, meta_type,
8853 // dir_flags, meta_flags, size, ctime, crtime, atime, mtime, md5, sha256, sha1, known, mime_type,
8854 // parent_path, data_source_obj_id,extension, uid_str, os_account_obj_id)
8855 // VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?, ?, ?, ?)
8856 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
8857 statement.clearParameters();
8858 statement.setLong(1, objectId);
8859 statement.setNull(2, java.sql.Types.BIGINT); // Not part of a file system
8860 statement.setString(3, fileName);
8861 statement.setShort(4, TskData.TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType());
8862 statement.setShort(5, (short) 1);
8864 statement.setShort(6, dirType.getValue());
8866 statement.setShort(7, metaType.getValue());
8868 statement.setShort(8, dirFlag.getValue());
8869 short metaFlags = (short) (TSK_FS_META_FLAG_ENUM.ALLOC.getValue() | TSK_FS_META_FLAG_ENUM.USED.getValue());
8870 statement.setShort(9, metaFlags);
8871 //prevent negative size
8872 long savedSize = size < 0 ? 0 : size;
8873 statement.setLong(10, savedSize);
8874 statement.setLong(11, ctime);
8875 statement.setLong(12, crtime);
8876 statement.setLong(13, atime);
8877 statement.setLong(14, mtime);
8878 statement.setString(15, md5);
8879 statement.setString(16, sha256);
8880 statement.setString(17, sha1Hash); // sha1
8881
8882 if (known != null) {
8883 statement.setByte(18, known.getFileKnownValue());
8884 } else {
8885 statement.setByte(18, FileKnown.UNKNOWN.getFileKnownValue());
8886 }
8887 statement.setString(19, mimeType);
8888 String parentPath;
8889 long dataSourceObjId;
8890
8891 if (parent instanceof AbstractFile) {
8892 AbstractFile parentFile = (AbstractFile) parent;
8893 if (isRootDirectory(parentFile, transaction)) {
8894 parentPath = "/";
8895 } else {
8896 parentPath = parentFile.getParentPath() + parent.getName() + "/"; //NON-NLS
8897 }
8898 dataSourceObjId = parentFile.getDataSourceObjectId();
8899 } else {
8900 parentPath = "/";
8901 dataSourceObjId = getDataSourceObjectId(connection, parent);
8902 }
8903 statement.setString(20, parentPath);
8904 statement.setLong(21, dataSourceObjId);
8905 final String extension = extractExtension(fileName);
8906 statement.setString(22, extension);
8907
8908 if (ownerAccount != null) {
8909 statement.setString(23, ownerAccount); // ownerUid
8910 } else {
8911 statement.setNull(23, java.sql.Types.VARCHAR);
8912 }
8913
8914 if (osAccountId != null) {
8915 statement.setLong(24, osAccountId); // osAccountObjId
8916 } else {
8917 statement.setNull(24, java.sql.Types.BIGINT);
8918 }
8919
8920 statement.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
8921
8922 connection.executeUpdate(statement);
8923 addFilePath(connection, objectId, localPath, encodingType);
8924 LocalFile localFile = new LocalFile(this,
8925 objectId,
8926 fileName,
8928 dirType,
8929 metaType,
8930 dirFlag,
8931 metaFlags,
8932 savedSize,
8933 ctime, crtime, atime, mtime,
8934 mimeType, md5, sha256, sha1Hash, known,
8935 parent.getId(), parentPath,
8936 dataSourceObjId,
8937 localPath,
8938 encodingType, extension,
8939 ownerAccount, osAccountId);
8940 if (!timelineEventsDisabled.get()) {
8941 getTimelineManager().addEventsForNewFile(localFile, connection);
8942 }
8943 return localFile;
8944
8945 } catch (SQLException ex) {
8946 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);
8947 } finally {
8948 closeStatement(queryStatement);
8949 }
8950 }
8951
8957 private class RootDirectoryKey {
8958
8959 private long dataSourceId;
8960 private Long fileSystemId;
8961
8962 RootDirectoryKey(long dataSourceId, Long fileSystemId) {
8963 this.dataSourceId = dataSourceId;
8964 this.fileSystemId = fileSystemId;
8965 }
8966
8967 @Override
8968 public int hashCode() {
8969 int hash = 7;
8970 hash = 41 * hash + Objects.hashCode(dataSourceId);
8971 hash = 41 * hash + Objects.hashCode(fileSystemId);
8972 return hash;
8973 }
8974
8975 @Override
8976 public boolean equals(Object obj) {
8977 if (this == obj) {
8978 return true;
8979 }
8980 if (obj == null) {
8981 return false;
8982 }
8983 if (getClass() != obj.getClass()) {
8984 return false;
8985 }
8986
8987 RootDirectoryKey otherKey = (RootDirectoryKey) obj;
8988 if (dataSourceId != otherKey.dataSourceId) {
8989 return false;
8990 }
8991
8992 if (fileSystemId != null) {
8993 return fileSystemId.equals(otherKey.fileSystemId);
8994 }
8995 return (otherKey.fileSystemId == null);
8996 }
8997 }
8998
9011 private boolean isRootDirectory(AbstractFile file, CaseDbTransaction transaction) throws TskCoreException {
9012
9013 // First check if we know the root directory for this data source and optionally
9014 // file system. There is only one root, so if we know it we can simply compare
9015 // this file ID to the known root directory.
9016 Long fsObjId = null;
9017 if (file instanceof FsContent) {
9018 fsObjId = ((FsContent) file).getFileSystemId();
9019 }
9020 RootDirectoryKey key = new RootDirectoryKey(file.getDataSourceObjectId(), fsObjId);
9021 synchronized (rootDirectoryMapLock) {
9022 if (rootDirectoryMap.containsKey(key)) {
9023 return rootDirectoryMap.get(key).equals(file.getId());
9024 }
9025 }
9026
9027 // Fallback cache. We store the result of each database lookup
9028 // so it won't be done multiple times in a row. In practice, this will
9029 // only be used if this method was never called on the root directory.
9030 Boolean isRoot = isRootDirectoryCache.getIfPresent(file.getId());
9031 if (isRoot != null) {
9032 return isRoot;
9033 }
9034
9035 CaseDbConnection connection = transaction.getConnection();
9036 Statement statement = null;
9037 ResultSet resultSet = null;
9038
9039 try {
9040 String query = String.format("SELECT ParentRow.type AS parent_type, ParentRow.obj_id AS parent_object_id "
9041 + "FROM tsk_objects ParentRow JOIN tsk_objects ChildRow ON ChildRow.par_obj_id = ParentRow.obj_id "
9042 + "WHERE ChildRow.obj_id = %s;", file.getId());
9043
9044 statement = connection.createStatement();
9045 resultSet = statement.executeQuery(query);
9046 if (resultSet.next()) {
9047 long parentId = resultSet.getLong("parent_object_id");
9048 if (parentId == 0) {
9049 return true;
9050 }
9051 int type = resultSet.getInt("parent_type");
9052 boolean result = type == TskData.ObjectType.IMG.getObjectType()
9053 || type == TskData.ObjectType.VS.getObjectType()
9054 || type == TskData.ObjectType.VOL.getObjectType()
9055 || type == TskData.ObjectType.FS.getObjectType();
9056 if (result == true) {
9057 synchronized (rootDirectoryMapLock) {
9058 // This is a root directory so save it
9059 rootDirectoryMap.put(key, file.getId());
9060 }
9061 }
9062 isRootDirectoryCache.put(file.getId(), result);
9063 return result;
9064
9065 } else {
9066 // This is a root directory so save it
9067 synchronized (rootDirectoryMapLock) {
9068 rootDirectoryMap.put(key, file.getId());
9069 }
9070 isRootDirectoryCache.put(file.getId(), true);
9071
9072 return true; // The file has no parent
9073
9074 }
9075 } catch (SQLException ex) {
9076 throw new TskCoreException(String.format("Failed to lookup parent of file (%s) with id %d", file.getName(), file.getId()), ex);
9077 } finally {
9078 closeResultSet(resultSet);
9079 closeStatement(statement);
9080 }
9081 }
9082
9102 public LayoutFile addLayoutFile(String fileName,
9103 long size,
9105 long ctime, long crtime, long atime, long mtime,
9106 List<TskFileRange> fileRanges,
9107 Content parent) throws TskCoreException {
9108
9109 if (null == parent) {
9110 throw new TskCoreException("Parent can not be null");
9111 }
9112
9113 String parentPath;
9114 if (parent instanceof AbstractFile) {
9115 parentPath = ((AbstractFile) parent).getParentPath() + parent.getName() + '/'; //NON-NLS
9116 } else {
9117 parentPath = "/";
9118 }
9119
9120 CaseDbTransaction transaction = null;
9121 Statement statement = null;
9122 ResultSet resultSet = null;
9123 try {
9124 transaction = beginTransaction();
9125 CaseDbConnection connection = transaction.getConnection();
9126
9127 /*
9128 * Insert a row for the layout file into the tsk_objects table:
9129 * INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
9130 */
9131 long newFileId = addObject(parent.getId(), TskData.ObjectType.ABSTRACTFILE.getObjectType(), connection);
9132
9133 /*
9134 * Insert a row for the file into the tsk_files table: INSERT INTO
9135 * tsk_files (obj_id, fs_obj_id, name, type, has_path, dir_type,
9136 * meta_type, dir_flags, meta_flags, size, ctime, crtime, atime,
9137 * mtime, md5, known, mime_type, parent_path,
9138 * data_source_obj_id,extenion, owner_uid, os_account_obj_id) VALUES
9139 * (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
9140 */
9141 PreparedStatement prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_FILE);
9142 prepStmt.clearParameters();
9143 prepStmt.setLong(1, newFileId); // obj_id
9144
9145 // If the parent is part of a file system, grab its file system ID
9146 Long fileSystemObjectId;
9147 if (0 != parent.getId()) {
9148 fileSystemObjectId = this.getFileSystemId(parent.getId(), connection);
9149 if (fileSystemObjectId != -1) {
9150 prepStmt.setLong(2, fileSystemObjectId);
9151 } else {
9152 prepStmt.setNull(2, java.sql.Types.BIGINT);
9153 fileSystemObjectId = null;
9154 }
9155 } else {
9156 prepStmt.setNull(2, java.sql.Types.BIGINT);
9157 fileSystemObjectId = null;
9158 }
9159 prepStmt.setString(3, fileName); // name
9160 prepStmt.setShort(4, TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType()); // type
9161 prepStmt.setShort(5, (short) 0); // has_path
9162 prepStmt.setShort(6, TSK_FS_NAME_TYPE_ENUM.REG.getValue()); // dir_type
9163 prepStmt.setShort(7, TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_REG.getValue()); // meta_type
9164 prepStmt.setShort(8, dirFlag.getValue()); // dir_flags
9165 prepStmt.setShort(9, metaFlag.getValue()); // meta_flags
9166 //prevent negative size
9167 long savedSize = size < 0 ? 0 : size;
9168 prepStmt.setLong(10, savedSize); // size
9169 prepStmt.setLong(11, ctime); // ctime
9170 prepStmt.setLong(12, crtime); // crtime
9171 prepStmt.setLong(13, atime); // atime
9172 prepStmt.setLong(14, mtime); // mtime
9173 prepStmt.setNull(15, java.sql.Types.VARCHAR); // MD5
9174 prepStmt.setNull(16, java.sql.Types.VARCHAR); // SHA-256
9175 prepStmt.setNull(17, java.sql.Types.VARCHAR); // SHA-1
9176
9177 prepStmt.setByte(18, FileKnown.UNKNOWN.getFileKnownValue()); // Known
9178 prepStmt.setNull(19, java.sql.Types.VARCHAR); // MIME type
9179 prepStmt.setString(20, parentPath); // parent path
9180 prepStmt.setLong(21, parent.getDataSource().getId()); // data_source_obj_id
9181
9182 prepStmt.setString(22, extractExtension(fileName)); //extension
9183
9184 prepStmt.setString(23, OsAccount.NO_OWNER_ID); // ownerUid
9185 prepStmt.setNull(24, java.sql.Types.BIGINT); // osAccountObjId
9186 prepStmt.setLong(25, TskData.CollectedStatus.UNKNOWN.getType()); // collected
9187
9188 connection.executeUpdate(prepStmt);
9189
9190 /*
9191 * Insert a row in the tsk_layout_file table for each chunk of the
9192 * carved file. INSERT INTO tsk_file_layout (obj_id, byte_start,
9193 * byte_len, sequence) VALUES (?, ?, ?, ?)
9194 */
9195 prepStmt = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LAYOUT_FILE);
9196 for (TskFileRange tskFileRange : fileRanges) {
9197 prepStmt.clearParameters();
9198 prepStmt.setLong(1, newFileId); // obj_id
9199 prepStmt.setLong(2, tskFileRange.getByteStart()); // byte_start
9200 prepStmt.setLong(3, tskFileRange.getByteLen()); // byte_len
9201 prepStmt.setLong(4, tskFileRange.getSequence()); // sequence
9202 connection.executeUpdate(prepStmt);
9203 }
9204
9205 /*
9206 * Create a layout file representation of the carved file.
9207 */
9208 LayoutFile layoutFile = new LayoutFile(this,
9209 newFileId,
9210 parent.getDataSource().getId(),
9211 fileSystemObjectId,
9212 fileName,
9216 dirFlag,
9217 metaFlag.getValue(),
9218 savedSize,
9219 ctime, crtime, atime, mtime,
9220 null, null, null,
9222 parentPath,
9223 null,
9224 OsAccount.NO_OWNER_ID,
9225 OsAccount.NO_ACCOUNT);
9226
9227 transaction.commit();
9228 transaction = null;
9229 return layoutFile;
9230
9231 } catch (SQLException ex) {
9232 throw new TskCoreException("Failed to add layout file " + fileName + " to case database", ex);
9233 } finally {
9234 closeResultSet(resultSet);
9235 closeStatement(statement);
9236
9237 if (null != transaction) {
9238 try {
9239 transaction.rollback();
9240 } catch (TskCoreException ex2) {
9241 logger.log(Level.SEVERE, "Failed to rollback transaction after exception", ex2);
9242 }
9243 }
9244 }
9245 }
9246
9256 private long getDataSourceObjectId(CaseDbConnection connection, Content content) throws TskCoreException {
9257 if (content == null) {
9258 throw new TskCoreException("Null Content parameter given");
9259 }
9260 if (content instanceof AbstractFile) {
9261 return ((AbstractFile) content).getDataSourceObjectId();
9262 } else {
9263 return getDataSourceObjectId(connection, content.getId());
9264 }
9265 }
9266
9279 private long getDataSourceObjectId(CaseDbConnection connection, long objectId) throws TskCoreException {
9281 Statement statement = null;
9282 ResultSet resultSet = null;
9283 try {
9284 statement = connection.createStatement();
9285 long dataSourceObjId;
9286 long ancestorId = objectId;
9287 do {
9288 dataSourceObjId = ancestorId;
9289 String query = String.format("SELECT par_obj_id FROM tsk_objects WHERE obj_id = %s;", ancestorId);
9290 resultSet = statement.executeQuery(query);
9291 if (resultSet.next()) {
9292 ancestorId = resultSet.getLong("par_obj_id");
9293 } else {
9294 throw new TskCoreException(String.format("tsk_objects table is corrupt, SQL query returned no result: %s", query));
9295 }
9296 resultSet.close();
9297 resultSet = null;
9298 } while (0 != ancestorId); // Not NULL
9299 return dataSourceObjId;
9300 } catch (SQLException ex) {
9301 throw new TskCoreException(String.format("Error finding root data source for object (obj_id = %d)", objectId), ex);
9302 } finally {
9303 closeResultSet(resultSet);
9304 closeStatement(statement);
9306 }
9307 }
9308
9320 private void addFilePath(CaseDbConnection connection, long objId, String path, TskData.EncodingType type) throws SQLException {
9321 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_LOCAL_PATH);
9322 statement.clearParameters();
9323 statement.setLong(1, objId);
9324 statement.setString(2, path);
9325 statement.setInt(3, type.getType());
9326 connection.executeUpdate(statement);
9327 }
9328
9340 private void updateFilePath(CaseDbConnection connection, long objId, String path, TskData.EncodingType type) throws SQLException {
9341 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_LOCAL_PATH);
9342 statement.clearParameters();
9343 statement.setString(1, path);
9344 statement.setInt(2, type.getType());
9345 statement.setLong(3, objId);
9346 connection.executeUpdate(statement);
9347 }
9348
9362 public List<AbstractFile> findFilesInFolder(String fileName, AbstractFile parentFile) throws TskCoreException {
9363 String ext = "";
9364 if (!containsLikeWildcard(fileName)) {
9365 ext = SleuthkitCase.extractExtension(fileName);
9366 }
9367
9368 CaseDbConnection connection = null;
9369 ResultSet rs = null;
9370 long parentId = parentFile.getId();
9371
9373 try {
9374 connection = connections.getConnection();
9375
9376 PreparedStatement statement;
9377 if (ext.isEmpty()) {
9378 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_PARENT_AND_NAME);
9379 statement.clearParameters();
9380 statement.setLong(1, parentId);
9381 statement.setString(2, fileName);
9382 } else {
9383 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_FILES_BY_EXTENSION_AND_PARENT_AND_NAME);
9384 statement.clearParameters();
9385 statement.setString(1, ext);
9386 statement.setLong(2, parentId);
9387 statement.setString(3, fileName);
9388 }
9389
9390 rs = connection.executeQuery(statement);
9391 return resultSetToAbstractFiles(rs, connection);
9392 } catch (SQLException ex) {
9393 throw new TskCoreException("Error getting AbstractFile children with name=" + fileName + " for Content parent with ID=" + parentFile.getId(), ex);
9394 } finally {
9395 closeResultSet(rs);
9396 closeConnection(connection);
9398 }
9399 }
9400
9412 public long countFilesWhere(String sqlWhereClause) throws TskCoreException {
9413 CaseDbConnection connection = null;
9414 Statement s = null;
9415 ResultSet rs = null;
9417 try {
9418 connection = connections.getConnection();
9419 s = connection.createStatement();
9420 rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
9421 rs.next();
9422 return rs.getLong("count");
9423 } catch (SQLException e) {
9424 throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.countFilesWhere().", e);
9425 } finally {
9426 closeResultSet(rs);
9427 closeStatement(s);
9428 closeConnection(connection);
9430 }
9431 }
9432
9450 public List<AbstractFile> findAllFilesWhere(String sqlWhereClause) throws TskCoreException {
9451 CaseDbConnection connection = null;
9452 Statement s = null;
9453 ResultSet rs = null;
9455 try {
9456 connection = connections.getConnection();
9457 s = connection.createStatement();
9458 rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
9459 return resultSetToAbstractFiles(rs, connection);
9460 } catch (SQLException e) {
9461 throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFilesWhere(): " + sqlWhereClause, e);
9462 } finally {
9463 closeResultSet(rs);
9464 closeStatement(s);
9465 closeConnection(connection);
9467 }
9468 }
9469
9488 public List<AbstractFile> findAllFilesInFolderWhere(long parentId, String sqlWhereClause) throws TskCoreException {
9489 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";
9491 try (CaseDbConnection connection = connections.getConnection()) {
9492 String query = String.format(queryTemplate, parentId, sqlWhereClause);
9493 try (Statement s = connection.createStatement(); ResultSet rs = connection.executeQuery(s, query)) {
9494 return resultSetToAbstractFiles(rs, connection);
9495 } catch (SQLException ex) {
9496 throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFilesInFolderWhere(): " + query, ex);
9497 }
9498 } finally {
9500 }
9501 }
9502
9515 public List<Long> findAllFileIdsWhere(String sqlWhereClause) throws TskCoreException {
9516 CaseDbConnection connection = null;
9517 Statement s = null;
9518 ResultSet rs = null;
9520 try {
9521 connection = connections.getConnection();
9522 s = connection.createStatement();
9523 rs = connection.executeQuery(s, "SELECT obj_id FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
9524 List<Long> ret = new ArrayList<>();
9525 while (rs.next()) {
9526 ret.add(rs.getLong("obj_id"));
9527 }
9528 return ret;
9529 } catch (SQLException e) {
9530 throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findAllFileIdsWhere(): " + sqlWhereClause, e);
9531 } finally {
9532 closeResultSet(rs);
9533 closeStatement(s);
9534 closeConnection(connection);
9536 }
9537 }
9538
9550 public List<AbstractFile> openFiles(Content dataSource, String filePath) throws TskCoreException {
9551
9552 // get the non-unique path (strip of image and volume path segments, if
9553 // the exist.
9554 String path = AbstractFile.createNonUniquePath(filePath).toLowerCase();
9555
9556 // split the file name from the parent path
9557 int lastSlash = path.lastIndexOf('/'); //NON-NLS
9558
9559 // if the last slash is at the end, strip it off
9560 if (lastSlash == path.length()) {
9561 path = path.substring(0, lastSlash - 1);
9562 lastSlash = path.lastIndexOf('/'); //NON-NLS
9563 }
9564
9565 String parentPath = path.substring(0, lastSlash);
9566 String fileName = path.substring(lastSlash);
9567
9568 return findFiles(dataSource, fileName, parentPath);
9569 }
9570
9581 public List<TskFileRange> getFileRanges(long id) throws TskCoreException {
9582 CaseDbConnection connection = null;
9583 Statement s = null;
9584 ResultSet rs = null;
9586 try {
9587 connection = connections.getConnection();
9588 s = connection.createStatement();
9589 rs = connection.executeQuery(s, "SELECT * FROM tsk_file_layout WHERE obj_id = " + id + " ORDER BY sequence");
9590 List<TskFileRange> ranges = new ArrayList<TskFileRange>();
9591 while (rs.next()) {
9592 TskFileRange range = new TskFileRange(rs.getLong("byte_start"), //NON-NLS
9593 rs.getLong("byte_len"), rs.getLong("sequence")); //NON-NLS
9594 ranges.add(range);
9595 }
9596 return ranges;
9597 } catch (SQLException ex) {
9598 throw new TskCoreException("Error getting TskFileLayoutRanges by id, id = " + id, ex);
9599 } finally {
9600 closeResultSet(rs);
9601 closeStatement(s);
9602 closeConnection(connection);
9604 }
9605 }
9606
9617 public Image getImageById(long id) throws TskCoreException {
9618 CaseDbConnection connection = null;
9619 Statement s = null;
9620 ResultSet rs = null;
9622 try {
9623 connection = connections.getConnection();
9624 s = connection.createStatement();
9625 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 "
9626 + "FROM tsk_image_info "
9627 + "INNER JOIN data_source_info ON tsk_image_info.obj_id = data_source_info.obj_id "
9628 + "LEFT JOIN tsk_image_names ON tsk_image_names.obj_id = data_source_info.obj_id "
9629 + "WHERE tsk_image_info.obj_id = " + id); //NON-NLS
9630
9631 List<String> imagePaths = new ArrayList<>();
9632 long type, ssize, size;
9633 String tzone, md5, sha1, sha256, name, device_id, imagePath;
9634
9635 if (rs.next()) {
9636 imagePath = rs.getString("name");
9637 if (imagePath != null) {
9638 imagePaths.add(imagePath);
9639 }
9640 type = rs.getLong("type"); //NON-NLS
9641 ssize = rs.getLong("ssize"); //NON-NLS
9642 tzone = rs.getString("tzone"); //NON-NLS
9643 size = rs.getLong("size"); //NON-NLS
9644 md5 = rs.getString("md5"); //NON-NLS
9645 sha1 = rs.getString("sha1"); //NON-NLS
9646 sha256 = rs.getString("sha256"); //NON-NLS
9647 name = rs.getString("display_name");
9648 if (name == null) {
9649 if (imagePaths.size() > 0) {
9650 String path = imagePaths.get(0);
9651 name = (new java.io.File(path)).getName();
9652 } else {
9653 name = "";
9654 }
9655 }
9656 device_id = rs.getString("device_id");
9657 } else {
9658 throw new TskCoreException("No image found for id: " + id);
9659 }
9660
9661 // image can have multiple paths, therefore there can be multiple rows in the result set
9662 while (rs.next()) {
9663 imagePath = rs.getString("name");
9664 if (imagePath != null) {
9665 imagePaths.add(imagePath);
9666 }
9667 }
9668
9669 return new Image(this, id, type, device_id, ssize, name,
9670 imagePaths.toArray(new String[imagePaths.size()]), tzone, md5, sha1, sha256, size);
9671 } catch (SQLException ex) {
9672 throw new TskCoreException("Error getting Image by id, id = " + id, ex);
9673 } finally {
9674 closeResultSet(rs);
9675 closeStatement(s);
9676 closeConnection(connection);
9678 }
9679 }
9680
9692 VolumeSystem getVolumeSystemById(long id, Content parent) throws TskCoreException {
9693 CaseDbConnection connection = null;
9694 Statement s = null;
9695 ResultSet rs = null;
9697 try {
9698 connection = connections.getConnection();
9699 s = connection.createStatement();
9700 rs = connection.executeQuery(s, "SELECT * FROM tsk_vs_info " //NON-NLS
9701 + "where obj_id = " + id); //NON-NLS
9702 if (rs.next()) {
9703 long type = rs.getLong("vs_type"); //NON-NLS
9704 long imgOffset = rs.getLong("img_offset"); //NON-NLS
9705 long blockSize = rs.getLong("block_size"); //NON-NLS
9706 VolumeSystem vs = new VolumeSystem(this, id, "", type, imgOffset, blockSize);
9707 vs.setParent(parent);
9708 return vs;
9709 } else {
9710 throw new TskCoreException("No volume system found for id:" + id);
9711 }
9712 } catch (SQLException ex) {
9713 throw new TskCoreException("Error getting Volume System by ID.", ex);
9714 } finally {
9715 closeResultSet(rs);
9716 closeStatement(s);
9717 closeConnection(connection);
9719 }
9720 }
9721
9730 VolumeSystem getVolumeSystemById(long id, long parentId) throws TskCoreException {
9731 VolumeSystem vs = getVolumeSystemById(id, null);
9732 vs.setParentId(parentId);
9733 return vs;
9734 }
9735
9747 FileSystem getFileSystemById(long id, Image parent) throws TskCoreException {
9748 return getFileSystemByIdHelper(id, parent);
9749 }
9750
9759 FileSystem getFileSystemById(long id, long parentId) throws TskCoreException {
9760 Volume vol = null;
9761 FileSystem fs = getFileSystemById(id, vol);
9762 fs.setParentId(parentId);
9763 return fs;
9764 }
9765
9777 FileSystem getFileSystemById(long id, Volume parent) throws TskCoreException {
9778 return getFileSystemByIdHelper(id, parent);
9779 }
9780
9792 Pool getPoolById(long id, Content parent) throws TskCoreException {
9793 return getPoolByIdHelper(id, parent);
9794 }
9795
9804 Pool getPoolById(long id, long parentId) throws TskCoreException {
9805 Pool pool = getPoolById(id, null);
9806 pool.setParentId(parentId);
9807 return pool;
9808 }
9809
9821 private Pool getPoolByIdHelper(long id, Content parent) throws TskCoreException {
9822
9824 try (CaseDbConnection connection = connections.getConnection();
9825 Statement s = connection.createStatement();
9826 ResultSet rs = connection.executeQuery(s, "SELECT * FROM tsk_pool_info " //NON-NLS
9827 + "where obj_id = " + id);) { //NON-NLS
9828 if (rs.next()) {
9829 Pool pool = new Pool(this, rs.getLong("obj_id"), TskData.TSK_POOL_TYPE_ENUM.valueOf(rs.getLong("pool_type")).getName(), rs.getLong("pool_type"));
9830 pool.setParent(parent);
9831
9832 return pool;
9833 } else {
9834 throw new TskCoreException("No pool found for ID:" + id);
9835 }
9836 } catch (SQLException ex) {
9837 throw new TskCoreException("Error getting Pool by ID", ex);
9838 } finally {
9840 }
9841 }
9842
9854 private FileSystem getFileSystemByIdHelper(long id, Content parent) throws TskCoreException {
9855 // see if we already have it
9856 // @@@ NOTE: this is currently kind of bad in that we are ignoring the parent value,
9857 // but it should be the same...
9858 synchronized (fileSystemIdMap) {
9859 if (fileSystemIdMap.containsKey(id)) {
9860 return fileSystemIdMap.get(id);
9861 }
9862 }
9863 CaseDbConnection connection = null;
9864 Statement s = null;
9865 ResultSet rs = null;
9867 try {
9868 connection = connections.getConnection();
9869 s = connection.createStatement();
9870 rs = connection.executeQuery(s, "SELECT * FROM tsk_fs_info " //NON-NLS
9871 + "where obj_id = " + id); //NON-NLS
9872 if (rs.next()) {
9873 TskData.TSK_FS_TYPE_ENUM fsType = TskData.TSK_FS_TYPE_ENUM.valueOf(rs.getInt("fs_type")); //NON-NLS
9874 FileSystem fs = new FileSystem(this, rs.getLong("obj_id"), "", rs.getLong("img_offset"), //NON-NLS
9875 fsType, rs.getLong("block_size"), rs.getLong("block_count"), //NON-NLS
9876 rs.getLong("root_inum"), rs.getLong("first_inum"), rs.getLong("last_inum")); //NON-NLS
9877 fs.setParent(parent);
9878 // save it for the next call
9879 synchronized (fileSystemIdMap) {
9880 fileSystemIdMap.put(id, fs);
9881 }
9882 return fs;
9883 } else {
9884 throw new TskCoreException("No file system found for id:" + id);
9885 }
9886 } catch (SQLException ex) {
9887 throw new TskCoreException("Error getting File System by ID", ex);
9888 } finally {
9889 closeResultSet(rs);
9890 closeStatement(s);
9891 closeConnection(connection);
9893 }
9894 }
9895
9907 Volume getVolumeById(long id, VolumeSystem parent) throws TskCoreException {
9908 CaseDbConnection connection = null;
9909 Statement s = null;
9910 ResultSet rs = null;
9912 try {
9913 connection = connections.getConnection();
9914 s = connection.createStatement();
9915 rs = connection.executeQuery(s, "SELECT * FROM tsk_vs_parts " //NON-NLS
9916 + "where obj_id = " + id); //NON-NLS
9917 if (rs.next()) {
9925 String description;
9926 try {
9927 description = rs.getString("desc");
9928 } catch (Exception ex) {
9929 description = rs.getString("descr");
9930 }
9931 Volume vol = new Volume(this, rs.getLong("obj_id"), rs.getLong("addr"), //NON-NLS
9932 rs.getLong("start"), rs.getLong("length"), rs.getLong("flags"), //NON-NLS
9933 description);
9934 vol.setParent(parent);
9935 return vol;
9936 } else {
9937 throw new TskCoreException("No volume found for id:" + id);
9938 }
9939 } catch (SQLException ex) {
9940 throw new TskCoreException("Error getting Volume by ID", ex);
9941 } finally {
9942 closeResultSet(rs);
9943 closeStatement(s);
9944 closeConnection(connection);
9946 }
9947 }
9948
9957 Volume getVolumeById(long id, long parentId) throws TskCoreException {
9958 Volume vol = getVolumeById(id, null);
9959 vol.setParentId(parentId);
9960 return vol;
9961 }
9962
9974 Directory getDirectoryById(long id, FileSystem parentFs) throws TskCoreException {
9975 CaseDbConnection connection = null;
9976 Statement s = null;
9977 ResultSet rs = null;
9979 try {
9980 connection = connections.getConnection();
9981 s = connection.createStatement();
9982 rs = connection.executeQuery(s, "SELECT * FROM tsk_files " //NON-NLS
9983 + "WHERE obj_id = " + id);
9984 Directory temp = null; //NON-NLS
9985 if (rs.next()) {
9986 final short type = rs.getShort("type"); //NON-NLS
9987 if (type == TSK_DB_FILES_TYPE_ENUM.FS.getFileType()) {
9988 if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()
9989 || rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()) { //NON-NLS
9990 temp = directory(rs, parentFs);
9991 }
9992 } else if (type == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()) {
9993 throw new TskCoreException("Expecting an FS-type directory, got virtual, id: " + id);
9994 }
9995 } else {
9996 throw new TskCoreException("No Directory found for id:" + id);
9997 }
9998 return temp;
9999 } catch (SQLException ex) {
10000 throw new TskCoreException("Error getting Directory by ID", ex);
10001 } finally {
10002 closeResultSet(rs);
10003 closeStatement(s);
10004 closeConnection(connection);
10006 }
10007 }
10008
10018 public Collection<FileSystem> getImageFileSystems(Image image) throws TskCoreException {
10019 List<FileSystem> fileSystems = new ArrayList<>();
10020 String queryStr = "SELECT * FROM tsk_fs_info WHERE data_source_obj_id = " + image.getId();
10021
10022 CaseDbConnection connection = null;
10023 Statement s = null;
10024 ResultSet rs = null;
10026 try {
10027 connection = connections.getConnection();
10028 s = connection.createStatement();
10029 rs = connection.executeQuery(s, queryStr); //NON-NLS
10030 while (rs.next()) {
10031 TskData.TSK_FS_TYPE_ENUM fsType = TskData.TSK_FS_TYPE_ENUM.valueOf(rs.getInt("fs_type")); //NON-NLS
10032 FileSystem fs = new FileSystem(this, rs.getLong("obj_id"), "", rs.getLong("img_offset"), //NON-NLS
10033 fsType, rs.getLong("block_size"), rs.getLong("block_count"), //NON-NLS
10034 rs.getLong("root_inum"), rs.getLong("first_inum"), rs.getLong("last_inum")); //NON-NLS
10035 fs.setParent(null);
10036 fileSystems.add(fs);
10037 }
10038 } catch (SQLException ex) {
10039 throw new TskCoreException("Error looking up files systems. Query: " + queryStr, ex); //NON-NLS
10040 } finally {
10041 closeResultSet(rs);
10042 closeStatement(s);
10043 closeConnection(connection);
10045 }
10046 return fileSystems;
10047 }
10048
10059 List<Content> getImageChildren(Image img) throws TskCoreException {
10060 Collection<ObjectInfo> childInfos = getChildrenInfo(img);
10061 List<Content> children = new ArrayList<Content>();
10062 for (ObjectInfo info : childInfos) {
10063 if (null != info.type) {
10064 switch (info.type) {
10065 case VS:
10066 children.add(getVolumeSystemById(info.id, img));
10067 break;
10068 case POOL:
10069 children.add(getPoolById(info.id, img));
10070 break;
10071 case FS:
10072 children.add(getFileSystemById(info.id, img));
10073 break;
10074 case ABSTRACTFILE:
10075 AbstractFile f = getAbstractFileById(info.id);
10076 if (f != null) {
10077 children.add(f);
10078 }
10079 break;
10080 case ARTIFACT:
10081 BlackboardArtifact art = getArtifactById(info.id);
10082 if (art != null) {
10083 children.add(art);
10084 }
10085 break;
10086 case REPORT:
10087 // Do nothing for now - see JIRA-3673
10088 break;
10089 default:
10090 throw new TskCoreException("Image has child of invalid type: " + info.type);
10091 }
10092 }
10093 }
10094 return children;
10095 }
10096
10107 List<Long> getImageChildrenIds(Image img) throws TskCoreException {
10108 Collection<ObjectInfo> childInfos = getChildrenInfo(img);
10109 List<Long> children = new ArrayList<Long>();
10110 for (ObjectInfo info : childInfos) {
10111 if (info.type == ObjectType.VS
10112 || info.type == ObjectType.POOL
10113 || info.type == ObjectType.FS
10114 || info.type == ObjectType.ABSTRACTFILE
10115 || info.type == ObjectType.ARTIFACT) {
10116 children.add(info.id);
10117 } else if (info.type == ObjectType.REPORT) {
10118 // Do nothing for now - see JIRA-3673
10119 } else {
10120 throw new TskCoreException("Image has child of invalid type: " + info.type);
10121 }
10122 }
10123 return children;
10124 }
10125
10136 List<Content> getPoolChildren(Pool pool) throws TskCoreException {
10137 Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
10138 List<Content> children = new ArrayList<Content>();
10139 for (ObjectInfo info : childInfos) {
10140 if (null != info.type) {
10141 switch (info.type) {
10142 case VS:
10143 children.add(getVolumeSystemById(info.id, pool));
10144 break;
10145 case ABSTRACTFILE:
10146 AbstractFile f = getAbstractFileById(info.id);
10147 if (f != null) {
10148 children.add(f);
10149 }
10150 break;
10151 case ARTIFACT:
10152 BlackboardArtifact art = getArtifactById(info.id);
10153 if (art != null) {
10154 children.add(art);
10155 }
10156 break;
10157 default:
10158 throw new TskCoreException("Pool has child of invalid type: " + info.type);
10159 }
10160 }
10161 }
10162 return children;
10163 }
10164
10175 List<Long> getPoolChildrenIds(Pool pool) throws TskCoreException {
10176 Collection<ObjectInfo> childInfos = getChildrenInfo(pool);
10177 List<Long> children = new ArrayList<Long>();
10178 for (ObjectInfo info : childInfos) {
10179 if (info.type == ObjectType.VS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
10180 children.add(info.id);
10181 } else {
10182 throw new TskCoreException("Pool has child of invalid type: " + info.type);
10183 }
10184 }
10185 return children;
10186 }
10187
10198 List<Content> getVolumeSystemChildren(VolumeSystem vs) throws TskCoreException {
10199 Collection<ObjectInfo> childInfos = getChildrenInfo(vs);
10200 List<Content> children = new ArrayList<Content>();
10201 for (ObjectInfo info : childInfos) {
10202 if (null != info.type) {
10203 switch (info.type) {
10204 case VOL:
10205 children.add(getVolumeById(info.id, vs));
10206 break;
10207 case ABSTRACTFILE:
10208 AbstractFile f = getAbstractFileById(info.id);
10209 if (f != null) {
10210 children.add(f);
10211 }
10212 break;
10213 case ARTIFACT:
10214 BlackboardArtifact art = getArtifactById(info.id);
10215 if (art != null) {
10216 children.add(art);
10217 }
10218 break;
10219 default:
10220 throw new TskCoreException("VolumeSystem has child of invalid type: " + info.type);
10221 }
10222 }
10223 }
10224 return children;
10225 }
10226
10237 List<Long> getVolumeSystemChildrenIds(VolumeSystem vs) throws TskCoreException {
10238 Collection<ObjectInfo> childInfos = getChildrenInfo(vs);
10239 List<Long> children = new ArrayList<Long>();
10240 for (ObjectInfo info : childInfos) {
10241 if (info.type == ObjectType.VOL || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
10242 children.add(info.id);
10243 } else {
10244 throw new TskCoreException("VolumeSystem has child of invalid type: " + info.type);
10245 }
10246 }
10247 return children;
10248 }
10249
10260 List<Content> getVolumeChildren(Volume vol) throws TskCoreException {
10261 Collection<ObjectInfo> childInfos = getChildrenInfo(vol);
10262 List<Content> children = new ArrayList<Content>();
10263 for (ObjectInfo info : childInfos) {
10264 if (null != info.type) {
10265 switch (info.type) {
10266 case POOL:
10267 children.add(getPoolById(info.id, vol));
10268 break;
10269 case FS:
10270 children.add(getFileSystemById(info.id, vol));
10271 break;
10272 case ABSTRACTFILE:
10273 AbstractFile f = getAbstractFileById(info.id);
10274 if (f != null) {
10275 children.add(f);
10276 }
10277 break;
10278 case ARTIFACT:
10279 BlackboardArtifact art = getArtifactById(info.id);
10280 if (art != null) {
10281 children.add(art);
10282 }
10283 break;
10284 default:
10285 throw new TskCoreException("Volume has child of invalid type: " + info.type);
10286 }
10287 }
10288 }
10289 return children;
10290 }
10291
10302 List<Long> getVolumeChildrenIds(Volume vol) throws TskCoreException {
10303 final Collection<ObjectInfo> childInfos = getChildrenInfo(vol);
10304 final List<Long> children = new ArrayList<Long>();
10305 for (ObjectInfo info : childInfos) {
10306 if (info.type == ObjectType.FS || info.type == ObjectType.ABSTRACTFILE || info.type == ObjectType.ARTIFACT) {
10307 children.add(info.id);
10308 } else {
10309 throw new TskCoreException("Volume has child of invalid type: " + info.type);
10310 }
10311 }
10312 return children;
10313 }
10314
10328 public Image addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone) throws TskCoreException {
10329 return addImageInfo(deviceObjId, imageFilePaths, timeZone, null);
10330 }
10331
10346 public Image addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone, Host host) throws TskCoreException {
10347 return addImageInfo(deviceObjId, imageFilePaths, timeZone, host, null);
10348 }
10349
10350
10366 @Beta
10367 public Image addImageInfo(long deviceObjId, List<String> imageFilePaths, String timeZone, Host host, String password) throws TskCoreException {
10368 long imageId = this.caseHandle.addImageInfo(deviceObjId, imageFilePaths, timeZone, host, password, this);
10369 return getImageById(imageId);
10370 }
10371
10381 public Map<Long, List<String>> getImagePaths() throws TskCoreException {
10382 CaseDbConnection connection = null;
10383 Statement s1 = null;
10384 ResultSet rs1 = null;
10386 try {
10387 connection = connections.getConnection();
10388 s1 = connection.createStatement();
10389 rs1 = connection.executeQuery(s1, "SELECT tsk_image_info.obj_id, tsk_image_names.name FROM tsk_image_info "
10390 + "LEFT JOIN tsk_image_names ON tsk_image_info.obj_id = tsk_image_names.obj_id"); //NON-NLS
10391 Map<Long, List<String>> imgPaths = new LinkedHashMap<Long, List<String>>();
10392 while (rs1.next()) {
10393 long obj_id = rs1.getLong("obj_id"); //NON-NLS
10394 String name = rs1.getString("name"); //NON-NLS
10395 List<String> imagePaths = imgPaths.get(obj_id);
10396 if (imagePaths == null) {
10397 List<String> paths = new ArrayList<String>();
10398 if (name != null) {
10399 paths.add(name);
10400 }
10401 imgPaths.put(obj_id, paths);
10402 } else {
10403 if (name != null) {
10404 imagePaths.add(name);
10405 }
10406 }
10407 }
10408 return imgPaths;
10409 } catch (SQLException ex) {
10410 throw new TskCoreException("Error getting image paths.", ex);
10411 } finally {
10412 closeResultSet(rs1);
10413 closeStatement(s1);
10414 closeConnection(connection);
10416 }
10417 }
10418
10430 private List<String> getImagePathsById(long objectId, CaseDbConnection connection) throws TskCoreException {
10431 List<String> imagePaths = new ArrayList<>();
10433 Statement statement = null;
10434 ResultSet resultSet = null;
10435 try {
10436 statement = connection.createStatement();
10437 resultSet = connection.executeQuery(statement, "SELECT name FROM tsk_image_names WHERE tsk_image_names.obj_id = " + objectId); //NON-NLS
10438 while (resultSet.next()) {
10439 imagePaths.add(resultSet.getString("name"));
10440 }
10441 } catch (SQLException ex) {
10442 throw new TskCoreException(String.format("Error getting image names with obj_id = %d", objectId), ex);
10443 } finally {
10444 closeResultSet(resultSet);
10445 closeStatement(statement);
10447 }
10448
10449 return imagePaths;
10450 }
10451
10458 public List<Image> getImages() throws TskCoreException {
10459 CaseDbConnection connection = null;
10460 Statement s = null;
10461 ResultSet rs = null;
10463 try {
10464 connection = connections.getConnection();
10465 s = connection.createStatement();
10466 rs = connection.executeQuery(s, "SELECT obj_id FROM tsk_image_info"); //NON-NLS
10467 Collection<Long> imageIDs = new ArrayList<Long>();
10468 while (rs.next()) {
10469 imageIDs.add(rs.getLong("obj_id")); //NON-NLS
10470 }
10471 List<Image> images = new ArrayList<Image>();
10472 for (long id : imageIDs) {
10473 images.add(getImageById(id));
10474 }
10475 return images;
10476 } catch (SQLException ex) {
10477 throw new TskCoreException("Error retrieving images.", ex);
10478 } finally {
10479 closeResultSet(rs);
10480 closeStatement(s);
10481 closeConnection(connection);
10483 }
10484 }
10485
10496 public void setImagePaths(long obj_id, List<String> paths) throws TskCoreException {
10497 CaseDbTransaction transaction = beginTransaction();
10498 try {
10499 setImagePaths(obj_id, paths, transaction);
10500 transaction.commit();
10501 transaction = null;
10502 } finally {
10503 if (transaction != null) {
10504 transaction.rollback();
10505 }
10506 }
10507 }
10508
10520 @Beta
10521 public void setImagePaths(long objId, List<String> paths, CaseDbTransaction trans) throws TskCoreException {
10522 try {
10523 PreparedStatement statement = trans.getConnection().getPreparedStatement(PREPARED_STATEMENT.DELETE_IMAGE_NAME);
10524 statement.clearParameters();
10525 statement.setLong(1, objId);
10526 trans.getConnection().executeUpdate(statement);
10527 for (int i = 0; i < paths.size(); i++) {
10528 statement = trans.getConnection().getPreparedStatement(PREPARED_STATEMENT.INSERT_IMAGE_NAME);
10529 statement.clearParameters();
10530 statement.setLong(1, objId);
10531 statement.setString(2, paths.get(i));
10532 statement.setLong(3, i);
10533 trans.getConnection().executeUpdate(statement);
10534 }
10535 } catch (SQLException ex) {
10536 throw new TskCoreException("Error updating image paths.", ex);
10537 }
10538 }
10539
10540
10552 void deleteDataSource(long dataSourceObjectId) throws TskCoreException {
10553
10554 // Check if this data source is the only one associated with its host. If so,
10555 // we will delete the host and other associated data.
10556 // Note that the cascading deletes were only added in schema 9.1, so we
10557 // would get an error trying to delete a host from older cases.
10558 Host hostToDelete = null;
10560 int major = version.getMajor();
10561 int minor = version.getMinor();
10562 if (major > 9 || (major == 9 && minor >= 1)) {
10563 hostToDelete = getHostManager().getHostByDataSource(dataSourceObjectId);
10564 if (getHostManager().getDataSourcesForHost(hostToDelete).size() != 1) {
10565 hostToDelete = null;
10566 }
10567 }
10568
10569 CaseDbConnection connection = null;
10570 Statement statement;
10572 try {
10573 connection = connections.getConnection();
10574 statement = connection.createStatement();
10575 connection.beginTransaction();
10576 // The following delete(s) uses a foreign key delete with cascade in the DB so that it will delete
10577 // all associated rows from tsk_object and its children. For large data sources this may take some time.
10578 statement.execute("DELETE FROM tsk_objects WHERE obj_id = " + dataSourceObjectId);
10579 // The following delete uses a foreign key delete with cascade in the DB so that it will delete all
10580 // associated rows from accounts table and its children.
10581 String accountSql = "DELETE FROM accounts WHERE account_id in (SELECT account_id FROM accounts "
10582 + "WHERE account_id NOT IN (SELECT account1_id FROM account_relationships) "
10583 + "AND account_id NOT IN (SELECT account2_id FROM account_relationships))";
10584 statement.execute(accountSql);
10585
10586 // Now delete any host that was only associated with this data source. This will cascade to delete
10587 // realms, os accounts, and os account attributes that were associated with the host.
10588 if (hostToDelete != null) {
10589 statement.execute("DELETE FROM tsk_hosts WHERE id = " + hostToDelete.getHostId());
10590
10591 // Clean up any stray OS Account objects
10592 String deleteOsAcctObjectsQuery = "DELETE FROM tsk_objects "
10593 + "WHERE type=" + TskData.ObjectType.OS_ACCOUNT.getObjectType() + " "
10594 + "AND obj_id NOT IN (SELECT os_account_obj_id FROM tsk_os_accounts WHERE os_account_obj_id IS NOT NULL)";
10595 statement.execute(deleteOsAcctObjectsQuery);
10596 }
10597
10598 connection.commitTransaction();
10599 } catch (SQLException ex) {
10600 rollbackTransaction(connection);
10601 throw new TskCoreException("Error deleting data source.", ex);
10602 } finally {
10603 closeConnection(connection);
10605 }
10606 }
10607
10633 List<AbstractFile> resultSetToAbstractFiles(ResultSet rs, CaseDbConnection connection) throws SQLException {
10634 ArrayList<AbstractFile> results = new ArrayList<AbstractFile>();
10635 try {
10636 while (rs.next()) {
10637 final short type = rs.getShort("type"); //NON-NLS
10638 if (type == TSK_DB_FILES_TYPE_ENUM.FS.getFileType()
10639 && (rs.getShort("meta_type") != TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue())) {
10640 FsContent result;
10641 if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()) { //NON-NLS
10642 result = directory(rs, null);
10643 } else {
10644 result = file(rs, null);
10645 }
10646 results.add(result);
10647 } else if (type == TSK_DB_FILES_TYPE_ENUM.VIRTUAL_DIR.getFileType()
10648 || (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue())) { //NON-NLS
10649 final VirtualDirectory virtDir = virtualDirectory(rs, connection);
10650 results.add(virtDir);
10651 } else if (type == TSK_DB_FILES_TYPE_ENUM.LOCAL_DIR.getFileType()) {
10652 final LocalDirectory localDir = localDirectory(rs);
10653 results.add(localDir);
10654 } else if (type == TSK_DB_FILES_TYPE_ENUM.UNALLOC_BLOCKS.getFileType()
10655 || type == TSK_DB_FILES_TYPE_ENUM.UNUSED_BLOCKS.getFileType()
10656 || type == TSK_DB_FILES_TYPE_ENUM.CARVED.getFileType()
10657 || type == TSK_DB_FILES_TYPE_ENUM.LAYOUT_FILE.getFileType()) {
10658 TSK_DB_FILES_TYPE_ENUM atype = TSK_DB_FILES_TYPE_ENUM.valueOf(type);
10659 String parentPath = rs.getString("parent_path"); //NON-NLS
10660 if (parentPath == null) {
10661 parentPath = "/"; //NON-NLS
10662 }
10663
10664 Long osAccountObjId = rs.getLong("os_account_obj_id");
10665 if (rs.wasNull()) {
10666 osAccountObjId = null;
10667 }
10668
10669 LayoutFile lf = new LayoutFile(this,
10670 rs.getLong("obj_id"), //NON-NLS
10671 rs.getLong("data_source_obj_id"),
10672 rs.getLong("fs_obj_id"),
10673 rs.getString("name"), //NON-NLS
10674 atype,
10675 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10676 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
10677 rs.getLong("size"), //NON-NLS
10678 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
10679 rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
10680 FileKnown.valueOf(rs.getByte("known")), parentPath,
10681 rs.getString("mime_type"),
10682 rs.getString("owner_uid"), osAccountObjId); //NON-NLS
10683 results.add(lf);
10684 } else if (type == TSK_DB_FILES_TYPE_ENUM.DERIVED.getFileType()) {
10685 final DerivedFile df;
10686 df = derivedFile(rs, connection, AbstractContent.UNKNOWN_ID);
10687 results.add(df);
10688 } else if (type == TSK_DB_FILES_TYPE_ENUM.LOCAL.getFileType()) {
10689 final LocalFile lf;
10690 lf = localFile(rs, connection, AbstractContent.UNKNOWN_ID);
10691 results.add(lf);
10692 } else if (type == TSK_DB_FILES_TYPE_ENUM.SLACK.getFileType()) {
10693 final SlackFile sf = slackFile(rs, null);
10694 results.add(sf);
10695 }
10696 } //end for each resultSet
10697 } catch (SQLException e) {
10698 logger.log(Level.SEVERE, "Error getting abstract files from result set", e); //NON-NLS
10699 }
10700
10701 return results;
10702 }
10703
10704 // This following methods generate AbstractFile objects from a ResultSet
10716 org.sleuthkit.datamodel.File file(ResultSet rs, FileSystem fs) throws SQLException {
10717 Long osAccountObjId = rs.getLong("os_account_obj_id");
10718 if (rs.wasNull()) {
10719 osAccountObjId = null;
10720 }
10721
10722 org.sleuthkit.datamodel.File f = new org.sleuthkit.datamodel.File(this, rs.getLong("obj_id"), //NON-NLS
10723 rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
10724 TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
10725 rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
10726 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10727 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10728 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
10729 rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
10730 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
10731 (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
10732 rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
10733 FileKnown.valueOf(rs.getByte("known")), //NON-NLS
10734 rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension"), rs.getString("owner_uid"),
10735 osAccountObjId, TskData.CollectedStatus.valueOf(rs.getInt("collected")), Collections.emptyList()); //NON-NLS
10736 f.setFileSystem(fs);
10737 return f;
10738 }
10739
10751 Directory directory(ResultSet rs, FileSystem fs) throws SQLException {
10752 Long osAccountObjId = rs.getLong("os_account_obj_id");
10753 if (rs.wasNull()) {
10754 osAccountObjId = null;
10755 }
10756
10757 Directory dir = new Directory(this, rs.getLong("obj_id"), rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
10758 TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
10759 rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
10760 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10761 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10762 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
10763 rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
10764 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
10765 rs.getShort("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
10766 rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
10767 FileKnown.valueOf(rs.getByte("known")), //NON-NLS
10768 rs.getString("parent_path"), rs.getString("owner_uid"), osAccountObjId); //NON-NLS
10769 dir.setFileSystem(fs);
10770 return dir;
10771 }
10772
10783 VirtualDirectory virtualDirectory(ResultSet rs, CaseDbConnection connection) throws SQLException {
10784 String parentPath = rs.getString("parent_path"); //NON-NLS
10785 if (parentPath == null) {
10786 parentPath = "";
10787 }
10788
10789 long objId = rs.getLong("obj_id");
10790 long dsObjId = rs.getLong("data_source_obj_id");
10791 if (objId == dsObjId) { // virtual directory is a data source
10792
10793 String deviceId = "";
10794 String timeZone = "";
10795 Statement s = null;
10796 ResultSet rsDataSourceInfo = null;
10797
10799 try {
10800 s = connection.createStatement();
10801 rsDataSourceInfo = connection.executeQuery(s, "SELECT device_id, time_zone FROM data_source_info WHERE obj_id = " + objId);
10802 if (rsDataSourceInfo.next()) {
10803 deviceId = rsDataSourceInfo.getString("device_id");
10804 timeZone = rsDataSourceInfo.getString("time_zone");
10805 }
10806 } catch (SQLException ex) {
10807 logger.log(Level.SEVERE, "Error data source info for datasource id " + objId, ex); //NON-NLS
10808 } finally {
10809 closeResultSet(rsDataSourceInfo);
10810 closeStatement(s);
10812 }
10813
10814 return new LocalFilesDataSource(this,
10815 objId, dsObjId,
10816 deviceId,
10817 rs.getString("name"),
10818 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10819 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10820 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")),
10821 rs.getShort("meta_flags"),
10822 timeZone,
10823 rs.getString("md5"),
10824 rs.getString("sha256"),
10825 rs.getString("sha1"),
10826 FileKnown.valueOf(rs.getByte("known")),
10827 parentPath);
10828 } else {
10829 final VirtualDirectory vd = new VirtualDirectory(this,
10830 objId, dsObjId,
10831 rs.getLong("fs_obj_id"),
10832 rs.getString("name"), //NON-NLS
10833 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10834 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10835 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
10836 rs.getShort("meta_flags"), rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"), //NON-NLS
10837 FileKnown.valueOf(rs.getByte("known")), parentPath); //NON-NLS
10838 return vd;
10839 }
10840 }
10841
10851 LocalDirectory localDirectory(ResultSet rs) throws SQLException {
10852 String parentPath = rs.getString("parent_path"); //NON-NLS
10853 if (parentPath == null) {
10854 parentPath = "";
10855 }
10856 final LocalDirectory ld = new LocalDirectory(this, rs.getLong("obj_id"), //NON-NLS
10857 rs.getLong("data_source_obj_id"), rs.getString("name"), //NON-NLS
10858 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10859 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10860 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
10861 rs.getShort("meta_flags"), rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"), //NON-NLS
10862 FileKnown.valueOf(rs.getByte("known")), parentPath); //NON-NLS
10863 return ld;
10864 }
10865
10879 private DerivedFile derivedFile(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
10880 boolean hasLocalPath = rs.getBoolean("has_path"); //NON-NLS
10881 long objId = rs.getLong("obj_id"); //NON-NLS
10882 String localPath = null;
10883 TskData.EncodingType encodingType = TskData.EncodingType.NONE;
10884 if (hasLocalPath) {
10885 ResultSet rsFilePath = null;
10887 try {
10888 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE);
10889 statement.clearParameters();
10890 statement.setLong(1, objId);
10891 rsFilePath = connection.executeQuery(statement);
10892 if (rsFilePath.next()) {
10893 localPath = rsFilePath.getString("path");
10894 encodingType = TskData.EncodingType.valueOf(rsFilePath.getInt("encoding_type"));
10895 }
10896 } catch (SQLException ex) {
10897 logger.log(Level.SEVERE, "Error getting encoding type for file " + objId, ex); //NON-NLS
10898 } finally {
10899 closeResultSet(rsFilePath);
10901 }
10902 }
10903 String parentPath = rs.getString("parent_path"); //NON-NLS
10904 if (parentPath == null) {
10905 parentPath = "";
10906 }
10907
10908 Long osAccountObjId = rs.getLong("os_account_obj_id");
10909 if (rs.wasNull()) {
10910 osAccountObjId = null;
10911 }
10912
10913 final DerivedFile df = new DerivedFile(this, objId, rs.getLong("data_source_obj_id"),
10914 rs.getLong("fs_obj_id"),
10915 rs.getString("name"), //NON-NLS
10916 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10917 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10918 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
10919 rs.getLong("size"), //NON-NLS
10920 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
10921 rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
10922 FileKnown.valueOf(rs.getByte("known")), //NON-NLS
10923 parentPath, localPath, parentId, rs.getString("mime_type"),
10924 encodingType, rs.getString("extension"),
10925 rs.getString("owner_uid"), osAccountObjId);
10926 return df;
10927 }
10928
10942 private LocalFile localFile(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
10943 long objId = rs.getLong("obj_id"); //NON-NLS
10944 String localPath = null;
10945 TskData.EncodingType encodingType = TskData.EncodingType.NONE;
10946 if (rs.getBoolean("has_path")) {
10947 ResultSet rsFilePath = null;
10949 try {
10950 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE);
10951 statement.clearParameters();
10952 statement.setLong(1, objId);
10953 rsFilePath = connection.executeQuery(statement);
10954 if (rsFilePath.next()) {
10955 localPath = rsFilePath.getString("path");
10956 encodingType = TskData.EncodingType.valueOf(rsFilePath.getInt("encoding_type"));
10957 }
10958 } catch (SQLException ex) {
10959 logger.log(Level.SEVERE, "Error getting encoding type for file " + objId, ex); //NON-NLS
10960 } finally {
10961 closeResultSet(rsFilePath);
10963 }
10964 }
10965 String parentPath = rs.getString("parent_path"); //NON-NLS
10966 if (null == parentPath) {
10967 parentPath = "";
10968 }
10969 Long osAccountObjId = rs.getLong("os_account_obj_id");
10970 if (rs.wasNull()) {
10971 osAccountObjId = null;
10972 }
10973
10974 LocalFile file = new LocalFile(this, objId, rs.getString("name"), //NON-NLS
10975 TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type")), //NON-NLS
10976 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
10977 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
10978 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"), //NON-NLS
10979 rs.getLong("size"), //NON-NLS
10980 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
10981 rs.getString("mime_type"), rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
10982 FileKnown.valueOf(rs.getByte("known")), //NON-NLS
10983 parentId, parentPath, rs.getLong("data_source_obj_id"),
10984 localPath, encodingType, rs.getString("extension"),
10985 rs.getString("owner_uid"), osAccountObjId);
10986 return file;
10987 }
10988
11000 org.sleuthkit.datamodel.SlackFile slackFile(ResultSet rs, FileSystem fs) throws SQLException {
11001 Long osAccountObjId = rs.getLong("os_account_obj_id");
11002 if (rs.wasNull()) {
11003 osAccountObjId = null;
11004 }
11005 org.sleuthkit.datamodel.SlackFile f = new org.sleuthkit.datamodel.SlackFile(this, rs.getLong("obj_id"), //NON-NLS
11006 rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"), //NON-NLS
11007 TskData.TSK_FS_ATTR_TYPE_ENUM.valueOf(rs.getShort("attr_type")), //NON-NLS
11008 rs.getInt("attr_id"), rs.getString("name"), rs.getLong("meta_addr"), rs.getInt("meta_seq"), //NON-NLS
11009 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")), //NON-NLS
11010 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")), //NON-NLS
11011 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), //NON-NLS
11012 rs.getShort("meta_flags"), rs.getLong("size"), //NON-NLS
11013 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"), //NON-NLS
11014 (short) rs.getInt("mode"), rs.getInt("uid"), rs.getInt("gid"), //NON-NLS
11015 rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
11016 FileKnown.valueOf(rs.getByte("known")), //NON-NLS
11017 rs.getString("parent_path"), rs.getString("mime_type"), rs.getString("extension"),
11018 rs.getString("owner_uid"), osAccountObjId); //NON-NLS
11019 f.setFileSystem(fs);
11020 return f;
11021 }
11022
11034 List<Content> fileChildren(ResultSet rs, CaseDbConnection connection, long parentId) throws SQLException {
11035 List<Content> children = new ArrayList<Content>();
11036
11037 while (rs.next()) {
11038 TskData.TSK_DB_FILES_TYPE_ENUM type = TskData.TSK_DB_FILES_TYPE_ENUM.valueOf(rs.getShort("type"));
11039
11040 if (null != type) {
11041 switch (type) {
11042 case FS:
11043 if (rs.getShort("meta_type") != TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_VIRT_DIR.getValue()) {
11044 FsContent result;
11045 if (rs.getShort("meta_type") == TSK_FS_META_TYPE_ENUM.TSK_FS_META_TYPE_DIR.getValue()) {
11046 result = directory(rs, null);
11047 } else {
11048 result = file(rs, null);
11049 }
11050 children.add(result);
11051 } else {
11052 VirtualDirectory virtDir = virtualDirectory(rs, connection);
11053 children.add(virtDir);
11054 }
11055 break;
11056 case VIRTUAL_DIR:
11057 VirtualDirectory virtDir = virtualDirectory(rs, connection);
11058 children.add(virtDir);
11059 break;
11060 case LOCAL_DIR:
11061 LocalDirectory localDir = localDirectory(rs);
11062 children.add(localDir);
11063 break;
11064 case UNALLOC_BLOCKS:
11065 case UNUSED_BLOCKS:
11066 case CARVED:
11067 case LAYOUT_FILE: {
11068 String parentPath = rs.getString("parent_path");
11069 if (parentPath == null) {
11070 parentPath = "";
11071 }
11072 Long osAccountObjId = rs.getLong("os_account_obj_id");
11073 if (rs.wasNull()) {
11074 osAccountObjId = null;
11075 }
11076 final LayoutFile lf = new LayoutFile(this, rs.getLong("obj_id"),
11077 rs.getLong("data_source_obj_id"), rs.getLong("fs_obj_id"),
11078 rs.getString("name"), type,
11079 TSK_FS_NAME_TYPE_ENUM.valueOf(rs.getShort("dir_type")),
11080 TSK_FS_META_TYPE_ENUM.valueOf(rs.getShort("meta_type")),
11081 TSK_FS_NAME_FLAG_ENUM.valueOf(rs.getShort("dir_flags")), rs.getShort("meta_flags"),
11082 rs.getLong("size"),
11083 rs.getLong("ctime"), rs.getLong("crtime"), rs.getLong("atime"), rs.getLong("mtime"),
11084 rs.getString("md5"), rs.getString("sha256"), rs.getString("sha1"),
11085 FileKnown.valueOf(rs.getByte("known")), parentPath, rs.getString("mime_type"),
11086 rs.getString("owner_uid"), osAccountObjId);
11087 children.add(lf);
11088 break;
11089 }
11090 case DERIVED:
11091 final DerivedFile df = derivedFile(rs, connection, parentId);
11092 children.add(df);
11093 break;
11094 case LOCAL: {
11095 final LocalFile lf = localFile(rs, connection, parentId);
11096 children.add(lf);
11097 break;
11098 }
11099 case SLACK: {
11100 final SlackFile sf = slackFile(rs, null);
11101 children.add(sf);
11102 break;
11103 }
11104 default:
11105 break;
11106 }
11107 }
11108 }
11109 return children;
11110 }
11111
11133 public CaseDbQuery executeQuery(String query) throws TskCoreException {
11134 return new CaseDbQuery(query);
11135 }
11136
11159 return new CaseDbQuery(query, true);
11160 }
11161
11169 CaseDbConnection getConnection() throws TskCoreException {
11170 return connections.getConnection();
11171 }
11172
11180 String getCaseHandleIdentifier() {
11181 return caseHandleIdentifier;
11182 }
11183
11184 @SuppressWarnings("deprecation")
11185 @Override
11186 protected void finalize() throws Throwable {
11187 try {
11188 close();
11189 } finally {
11190 super.finalize();
11191 }
11192 }
11193
11197 public void close() {
11199
11200 try {
11201 connections.close();
11202 } catch (TskCoreException ex) {
11203 logger.log(Level.SEVERE, "Error closing database connection pool.", ex); //NON-NLS
11204 }
11205
11206 fileSystemIdMap.clear();
11207
11208 try {
11209 if (this.caseHandle != null) {
11210 this.caseHandle.free();
11211 this.caseHandle = null;
11212 }
11213 } catch (TskCoreException ex) {
11214 logger.log(Level.SEVERE, "Error freeing case handle.", ex); //NON-NLS
11215 } finally {
11217 }
11218
11219 if (this.lockResources != null) {
11220 try {
11221 this.lockResources.close();
11222 } catch (Exception ex) {
11223 logger.log(Level.SEVERE, "Error closing lock resources.", ex); //NON-NLS
11224 }
11225 }
11226 }
11227
11240 public boolean setKnown(AbstractFile file, FileKnown fileKnown) throws TskCoreException {
11241 long id = file.getId();
11242 FileKnown currentKnown = file.getKnown();
11243 if (currentKnown.compareTo(fileKnown) > 0) {
11244 return false;
11245 }
11247 try (CaseDbConnection connection = connections.getConnection();
11248 Statement statement = connection.createStatement();) {
11249 connection.executeUpdate(statement, "UPDATE tsk_files " //NON-NLS
11250 + "SET known='" + fileKnown.getFileKnownValue() + "' " //NON-NLS
11251 + "WHERE obj_id=" + id); //NON-NLS
11252
11253 file.setKnown(fileKnown);
11254 } catch (SQLException ex) {
11255 throw new TskCoreException("Error setting Known status.", ex);
11256 } finally {
11258 }
11259 return true;
11260 }
11261
11270 void setFileName(String name, long objId) throws TskCoreException {
11272 try (CaseDbConnection connection = connections.getConnection();) {
11273 PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_FILE_NAME);
11274 preparedStatement.clearParameters();
11275 preparedStatement.setString(1, name);
11276 preparedStatement.setLong(2, objId);
11277 connection.executeUpdate(preparedStatement);
11278 } catch (SQLException ex) {
11279 throw new TskCoreException(String.format("Error updating while the name for object ID %d to %s", objId, name), ex);
11280 } finally {
11282 }
11283 }
11284
11293 void setImageName(String name, long objId) throws TskCoreException {
11295 try (CaseDbConnection connection = connections.getConnection();) {
11296 PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_IMAGE_NAME);
11297 preparedStatement.clearParameters();
11298 preparedStatement.setString(1, name);
11299 preparedStatement.setLong(2, objId);
11300 connection.executeUpdate(preparedStatement);
11301 } catch (SQLException ex) {
11302 throw new TskCoreException(String.format("Error updating while the name for object ID %d to %s", objId, name), ex);
11303 } finally {
11305 }
11306 }
11307
11322 void setImageSizes(Image image, long totalSize, long sectorSize) throws TskCoreException {
11323
11325 try (CaseDbConnection connection = connections.getConnection();) {
11326 PreparedStatement preparedStatement = connection.getPreparedStatement(SleuthkitCase.PREPARED_STATEMENT.UPDATE_IMAGE_SIZES);
11327 preparedStatement.clearParameters();
11328 preparedStatement.setLong(1, totalSize);
11329 preparedStatement.setLong(2, sectorSize);
11330 preparedStatement.setLong(3, image.getId());
11331 connection.executeUpdate(preparedStatement);
11332 } catch (SQLException ex) {
11333 throw new TskCoreException(String.format("Error updating image sizes to %d and sector size to %d for object ID %d ", totalSize, sectorSize, image.getId()), ex);
11334 } finally {
11336 }
11337 }
11338
11353 @Beta
11354 public void updateFile(long fileObjId, long size, long mtime, long atime, long ctime, long crtime, String userSid, Long osAcctObjId) throws TskCoreException {
11355
11356 String updateString = "UPDATE tsk_files SET size = ?, mtime = ?, atime = ?, ctime = ?, crtime = ?, "
11357 + " owner_uid = ?, os_account_obj_id = ? WHERE obj_id = ?";
11358
11360 try (CaseDbConnection connection = connections.getConnection();
11361 PreparedStatement preparedStatement = connection.getPreparedStatement(updateString, Statement.NO_GENERATED_KEYS);) {
11362
11363 preparedStatement.clearParameters();
11364
11365 preparedStatement.setLong(1, size);
11366 preparedStatement.setLong(2, mtime);
11367 preparedStatement.setLong(3, atime);
11368 preparedStatement.setLong(4, ctime);
11369 preparedStatement.setLong(5, crtime);
11370 preparedStatement.setString(6, userSid);
11371
11372 if (osAcctObjId != null) {
11373 preparedStatement.setLong(7, osAcctObjId);
11374 } else {
11375 preparedStatement.setNull(7, java.sql.Types.BIGINT);
11376 }
11377
11378 preparedStatement.setLong(8, fileObjId);
11379
11380 connection.executeUpdate(preparedStatement);
11381 } catch (SQLException ex) {
11382 throw new TskCoreException(String.format("Error updating file (obj_id = %s)", fileObjId), ex);
11383 } finally {
11385 }
11386 }
11387
11397 public void setFileMIMEType(AbstractFile file, String mimeType) throws TskCoreException {
11399 try (CaseDbConnection connection = connections.getConnection();
11400 Statement statement = connection.createStatement()) {
11401 connection.executeUpdate(statement, String.format("UPDATE tsk_files SET mime_type = '%s' WHERE obj_id = %d", mimeType, file.getId()));
11402 file.setMIMEType(mimeType);
11403 } catch (SQLException ex) {
11404 throw new TskCoreException(String.format("Error setting MIME type for file (obj_id = %s)", file.getId()), ex);
11405 } finally {
11407 }
11408 }
11409
11421
11422 // get the flags, reset the ALLOC flag, and set the UNALLOC flag
11423 short metaFlag = file.getMetaFlagsAsInt();
11424 Set<TSK_FS_META_FLAG_ENUM> metaFlagAsSet = TSK_FS_META_FLAG_ENUM.valuesOf(metaFlag);
11425 metaFlagAsSet.remove(TSK_FS_META_FLAG_ENUM.ALLOC);
11426 metaFlagAsSet.add(TSK_FS_META_FLAG_ENUM.UNALLOC);
11427
11428 short newMetaFlgs = TSK_FS_META_FLAG_ENUM.toInt(metaFlagAsSet);
11429 short newDirFlags = TSK_FS_NAME_FLAG_ENUM.UNALLOC.getValue();
11430
11432 try (CaseDbConnection connection = connections.getConnection();
11433 Statement statement = connection.createStatement();) {
11434 connection.executeUpdate(statement, String.format("UPDATE tsk_files SET meta_flags = '%d', dir_flags = '%d' WHERE obj_id = %d", newMetaFlgs, newDirFlags, file.getId()));
11435
11436 file.removeMetaFlag(TSK_FS_META_FLAG_ENUM.ALLOC);
11437 file.setMetaFlag(TSK_FS_META_FLAG_ENUM.UNALLOC);
11438
11439 file.setDirFlag(TSK_FS_NAME_FLAG_ENUM.UNALLOC);
11440
11441 } catch (SQLException ex) {
11442 throw new TskCoreException(String.format("Error setting unalloc meta flag for file (obj_id = %s)", file.getId()), ex);
11443 } finally {
11445 }
11446 }
11447
11457 void setMd5Hash(AbstractFile file, String md5Hash) throws TskCoreException {
11458 if (md5Hash == null) {
11459 return;
11460 }
11461 long id = file.getId();
11463 try (CaseDbConnection connection = connections.getConnection();) {
11464 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_FILE_MD5);
11465 statement.clearParameters();
11466 statement.setString(1, md5Hash.toLowerCase());
11467 statement.setLong(2, id);
11468 connection.executeUpdate(statement);
11469 file.setMd5Hash(md5Hash.toLowerCase());
11470 } catch (SQLException ex) {
11471 throw new TskCoreException("Error setting MD5 hash", ex);
11472 } finally {
11474 }
11475 }
11476
11486 void setMd5ImageHash(Image img, String md5Hash) throws TskCoreException {
11487 if (md5Hash == null) {
11488 return;
11489 }
11490 long id = img.getId();
11492 try (CaseDbConnection connection = connections.getConnection();) {
11493 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_MD5);
11494 statement.clearParameters();
11495 statement.setString(1, md5Hash.toLowerCase());
11496 statement.setLong(2, id);
11497 connection.executeUpdate(statement);
11498 } catch (SQLException ex) {
11499 throw new TskCoreException("Error setting MD5 hash", ex);
11500 } finally {
11502 }
11503 }
11504
11515 String getMd5ImageHash(Image img) throws TskCoreException {
11516 long id = img.getId();
11517 CaseDbConnection connection = null;
11518 ResultSet rs = null;
11519 String hash = "";
11521 try {
11522 connection = connections.getConnection();
11523
11524 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_MD5);
11525 statement.clearParameters();
11526 statement.setLong(1, id);
11527 rs = connection.executeQuery(statement);
11528 if (rs.next()) {
11529 hash = rs.getString("md5");
11530 }
11531 return hash;
11532 } catch (SQLException ex) {
11533 throw new TskCoreException("Error getting MD5 hash", ex);
11534 } finally {
11535 closeResultSet(rs);
11536 closeConnection(connection);
11538 }
11539 }
11540
11550 void setSha1ImageHash(Image img, String sha1Hash) throws TskCoreException {
11551 if (sha1Hash == null) {
11552 return;
11553 }
11554 long id = img.getId();
11556 try (CaseDbConnection connection = connections.getConnection();) {
11557 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_SHA1);
11558 statement.clearParameters();
11559 statement.setString(1, sha1Hash.toLowerCase());
11560 statement.setLong(2, id);
11561 connection.executeUpdate(statement);
11562 } catch (SQLException ex) {
11563 throw new TskCoreException("Error setting SHA1 hash", ex);
11564 } finally {
11566 }
11567 }
11568
11579 String getSha1ImageHash(Image img) throws TskCoreException {
11580 long id = img.getId();
11581 CaseDbConnection connection = null;
11582 ResultSet rs = null;
11583 String hash = "";
11585 try {
11586 connection = connections.getConnection();
11587
11588 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_SHA1);
11589 statement.clearParameters();
11590 statement.setLong(1, id);
11591 rs = connection.executeQuery(statement);
11592 if (rs.next()) {
11593 hash = rs.getString("sha1");
11594 }
11595 return hash;
11596 } catch (SQLException ex) {
11597 throw new TskCoreException("Error getting SHA1 hash", ex);
11598 } finally {
11599 closeResultSet(rs);
11600 closeConnection(connection);
11602 }
11603 }
11604
11614 void setSha256ImageHash(Image img, String sha256Hash) throws TskCoreException {
11615 if (sha256Hash == null) {
11616 return;
11617 }
11618 long id = img.getId();
11620 try (CaseDbConnection connection = connections.getConnection();) {
11621 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_SHA256);
11622 statement.clearParameters();
11623 statement.setString(1, sha256Hash.toLowerCase());
11624 statement.setLong(2, id);
11625 connection.executeUpdate(statement);
11626 } catch (SQLException ex) {
11627 throw new TskCoreException("Error setting SHA256 hash", ex);
11628 } finally {
11630 }
11631 }
11632
11643 String getSha256ImageHash(Image img) throws TskCoreException {
11644 long id = img.getId();
11645 CaseDbConnection connection = null;
11646 ResultSet rs = null;
11647 String hash = "";
11649 try {
11650 connection = connections.getConnection();
11651
11652 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_IMAGE_SHA256);
11653 statement.clearParameters();
11654 statement.setLong(1, id);
11655 rs = connection.executeQuery(statement);
11656 if (rs.next()) {
11657 hash = rs.getString("sha256");
11658 }
11659 return hash;
11660 } catch (SQLException ex) {
11661 throw new TskCoreException("Error setting SHA256 hash", ex);
11662 } finally {
11663 closeResultSet(rs);
11664 closeConnection(connection);
11666 }
11667 }
11668
11677 void setAcquisitionDetails(DataSource datasource, String details) throws TskCoreException {
11678
11679 long id = datasource.getId();
11681 try (CaseDbConnection connection = connections.getConnection();) {
11682 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
11683 statement.clearParameters();
11684 statement.setString(1, details);
11685 statement.setLong(2, id);
11686 connection.executeUpdate(statement);
11687 } catch (SQLException ex) {
11688 throw new TskCoreException("Error setting acquisition details", ex);
11689 } finally {
11691 }
11692 }
11693
11705 void setAcquisitionToolDetails(DataSource datasource, String name, String version, String settings) throws TskCoreException {
11706
11707 long id = datasource.getId();
11709 try (CaseDbConnection connection = connections.getConnection();) {
11710 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_TOOL_SETTINGS);
11711 statement.clearParameters();
11712 statement.setString(1, settings);
11713 statement.setString(2, name);
11714 statement.setString(3, version);
11715 statement.setLong(4, id);
11716 connection.executeUpdate(statement);
11717 } catch (SQLException ex) {
11718 throw new TskCoreException("Error setting acquisition details", ex);
11719 } finally {
11721 }
11722 }
11723
11733 void setAcquisitionDetails(long dataSourceId, String details, CaseDbTransaction trans) throws TskCoreException {
11734 try {
11735 CaseDbConnection connection = trans.getConnection();
11736 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_ACQUISITION_DETAILS);
11737 statement.clearParameters();
11738 statement.setString(1, details);
11739 statement.setLong(2, dataSourceId);
11740 connection.executeUpdate(statement);
11741 } catch (SQLException ex) {
11742 throw new TskCoreException("Error setting acquisition details", ex);
11743 }
11744 }
11745
11755 String getAcquisitionDetails(DataSource datasource) throws TskCoreException {
11756 long id = datasource.getId();
11757 CaseDbConnection connection = null;
11758 ResultSet rs = null;
11759 String hash = "";
11761 try {
11762 connection = connections.getConnection();
11763
11764 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ACQUISITION_DETAILS);
11765 statement.clearParameters();
11766 statement.setLong(1, id);
11767 rs = connection.executeQuery(statement);
11768 if (rs.next()) {
11769 hash = rs.getString("acquisition_details");
11770 }
11771 return hash;
11772 } catch (SQLException ex) {
11773 throw new TskCoreException("Error setting acquisition details", ex);
11774 } finally {
11775 closeResultSet(rs);
11776 closeConnection(connection);
11778 }
11779 }
11780
11791 String getDataSourceInfoString(DataSource datasource, String columnName) throws TskCoreException {
11792 long id = datasource.getId();
11793 CaseDbConnection connection = null;
11794 ResultSet rs = null;
11795 String returnValue = "";
11797 try {
11798 connection = connections.getConnection();
11799
11800 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ACQUISITION_TOOL_SETTINGS);
11801 statement.clearParameters();
11802 statement.setLong(1, id);
11803 rs = connection.executeQuery(statement);
11804 if (rs.next()) {
11805 returnValue = rs.getString(columnName);
11806 }
11807 return returnValue;
11808 } catch (SQLException ex) {
11809 throw new TskCoreException("Error setting acquisition details", ex);
11810 } finally {
11811 closeResultSet(rs);
11812 closeConnection(connection);
11814 }
11815 }
11816
11827 Long getDataSourceInfoLong(DataSource datasource, String columnName) throws TskCoreException {
11828 long id = datasource.getId();
11829 CaseDbConnection connection = null;
11830 ResultSet rs = null;
11831 Long returnValue = null;
11833 try {
11834 connection = connections.getConnection();
11835
11836 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ACQUISITION_TOOL_SETTINGS);
11837 statement.clearParameters();
11838 statement.setLong(1, id);
11839 rs = connection.executeQuery(statement);
11840 if (rs.next()) {
11841 returnValue = rs.getLong(columnName);
11842 }
11843 return returnValue;
11844 } catch (SQLException ex) {
11845 throw new TskCoreException("Error setting acquisition details", ex);
11846 } finally {
11847 closeResultSet(rs);
11848 closeConnection(connection);
11850 }
11851 }
11852
11864 if (newStatus == null) {
11865 return;
11866 }
11868 try (CaseDbConnection connection = connections.getConnection();
11869 Statement statement = connection.createStatement();) {
11870 connection.executeUpdate(statement, "UPDATE blackboard_artifacts "
11871 + " SET review_status_id=" + newStatus.getID()
11872 + " WHERE blackboard_artifacts.artifact_id = " + artifact.getArtifactID());
11873 } catch (SQLException ex) {
11874 throw new TskCoreException("Error setting review status", ex);
11875 } finally {
11877 }
11878 }
11879
11891 CaseDbConnection connection = null;
11892 Statement s = null;
11893 ResultSet rs = null;
11895 try {
11896 connection = connections.getConnection();
11897 s = connection.createStatement();
11898 Short contentShort = contentType.getValue();
11899 rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files WHERE meta_type = '" + contentShort.toString() + "'"); //NON-NLS
11900 int count = 0;
11901 if (rs.next()) {
11902 count = rs.getInt("count");
11903 }
11904 return count;
11905 } catch (SQLException ex) {
11906 throw new TskCoreException("Error getting number of objects.", ex);
11907 } finally {
11908 closeResultSet(rs);
11909 closeStatement(s);
11910 closeConnection(connection);
11912 }
11913 }
11914
11923 public static String escapeSingleQuotes(String text) {
11924 String escapedText = null;
11925 if (text != null) {
11926 escapedText = text.replaceAll("'", "''");
11927 }
11928 return escapedText;
11929 }
11930
11938 public List<AbstractFile> findFilesByMd5(String md5Hash) {
11939 if (md5Hash == null) {
11940 return Collections.<AbstractFile>emptyList();
11941 }
11942
11943 CaseDbConnection connection = null;
11944 Statement s = null;
11945 ResultSet rs = null;
11947 try {
11948 connection = connections.getConnection();
11949 s = connection.createStatement();
11950 rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " //NON-NLS
11951 + " md5 = '" + md5Hash.toLowerCase() + "' " //NON-NLS
11952 + "AND size > 0"); //NON-NLS
11953 return resultSetToAbstractFiles(rs, connection);
11954 } catch (SQLException | TskCoreException ex) {
11955 logger.log(Level.WARNING, "Error querying database.", ex); //NON-NLS
11956 } finally {
11957 closeResultSet(rs);
11958 closeStatement(s);
11959 closeConnection(connection);
11961 }
11962 return Collections.<AbstractFile>emptyList();
11963 }
11964
11971 public boolean allFilesMd5Hashed() {
11972 boolean allFilesAreHashed = false;
11973
11974 CaseDbConnection connection = null;
11975 Statement s = null;
11976 ResultSet rs = null;
11978 try {
11979 connection = connections.getConnection();
11980 s = connection.createStatement();
11981 rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files " //NON-NLS
11982 + "WHERE dir_type = '" + TskData.TSK_FS_NAME_TYPE_ENUM.REG.getValue() + "' " //NON-NLS
11983 + "AND md5 IS NULL " //NON-NLS
11984 + "AND size > '0'"); //NON-NLS
11985 if (rs.next() && rs.getInt("count") == 0) {
11986 allFilesAreHashed = true;
11987 }
11988 } catch (SQLException | TskCoreException ex) {
11989 logger.log(Level.WARNING, "Failed to query whether all files have MD5 hashes", ex); //NON-NLS
11990 } finally {
11991 closeResultSet(rs);
11992 closeStatement(s);
11993 closeConnection(connection);
11995 }
11996 return allFilesAreHashed;
11997 }
11998
12004 public int countFilesMd5Hashed() {
12005 int count = 0;
12006
12008 CaseDbConnection connection = null;
12009 Statement s = null;
12010 ResultSet rs = null;
12011 try {
12012 connection = connections.getConnection();
12013 s = connection.createStatement();
12014 rs = connection.executeQuery(s, "SELECT COUNT(*) AS count FROM tsk_files " //NON-NLS
12015 + "WHERE md5 IS NOT NULL " //NON-NLS
12016 + "AND size > '0'"); //NON-NLS
12017 if (rs.next()) {
12018 count = rs.getInt("count");
12019 }
12020 } catch (SQLException | TskCoreException ex) {
12021 logger.log(Level.WARNING, "Failed to query for all the files.", ex); //NON-NLS
12022 } finally {
12023 closeResultSet(rs);
12024 closeStatement(s);
12025 closeConnection(connection);
12027 }
12028 return count;
12029
12030 }
12031
12040 public List<TagName> getAllTagNames() throws TskCoreException {
12041 CaseDbConnection connection = null;
12042 ResultSet resultSet = null;
12044 try {
12045 connection = connections.getConnection();
12046
12047 // SELECT * FROM tag_names
12048 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES);
12049 resultSet = connection.executeQuery(statement);
12050 ArrayList<TagName> tagNames = new ArrayList<>();
12051 while (resultSet.next()) {
12052 tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12053 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12054 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
12055 }
12056 return tagNames;
12057 } catch (SQLException ex) {
12058 throw new TskCoreException("Error selecting rows from tag_names table", ex);
12059 } finally {
12060 closeResultSet(resultSet);
12061 closeConnection(connection);
12063 }
12064 }
12065
12076 public List<TagName> getTagNamesInUse() throws TskCoreException {
12077 CaseDbConnection connection = null;
12078 ResultSet resultSet = null;
12080 try {
12081 connection = connections.getConnection();
12082
12083 // 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)
12084 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES_IN_USE);
12085 resultSet = connection.executeQuery(statement);
12086 ArrayList<TagName> tagNames = new ArrayList<>();
12087 while (resultSet.next()) {
12088 tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12089 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12090 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
12091 }
12092 return tagNames;
12093 } catch (SQLException ex) {
12094 throw new TskCoreException("Error selecting rows from tag_names table", ex);
12095 } finally {
12096 closeResultSet(resultSet);
12097 closeConnection(connection);
12099 }
12100 }
12101
12114 public List<TagName> getTagNamesInUse(long dsObjId) throws TskCoreException {
12115
12116 ArrayList<TagName> tagNames = new ArrayList<>();
12117 // SELECT * FROM tag_names WHERE tag_name_id IN
12118 // ( 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 = ? "
12119 // UNION
12120 // 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 = ? )
12121 // )
12122 CaseDbConnection connection = null;
12123 ResultSet resultSet = null;
12125 try {
12126 connection = connections.getConnection();
12127
12128 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_TAG_NAMES_IN_USE_BY_DATASOURCE);
12129 statement.setLong(1, dsObjId);
12130 statement.setLong(2, dsObjId);
12131 resultSet = connection.executeQuery(statement); //NON-NLS
12132 while (resultSet.next()) {
12133 tagNames.add(new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12134 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12135 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"))); //NON-NLS
12136 }
12137 return tagNames;
12138 } catch (SQLException ex) {
12139 throw new TskCoreException("Failed to get tag names in use for data source objID : " + dsObjId, ex);
12140 } finally {
12141 closeResultSet(resultSet);
12142 closeConnection(connection);
12144 }
12145 }
12146
12160 @Deprecated
12161 @SuppressWarnings("deprecation")
12162 public TagName addTagName(String displayName, String description, TagName.HTML_COLOR color) throws TskCoreException {
12163 return addOrUpdateTagName(displayName, description, color, TskData.FileKnown.UNKNOWN);
12164 }
12165
12182 @Deprecated
12183 public TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus) throws TskCoreException {
12184 return getTaggingManager().addOrUpdateTagName(displayName, description, color, knownStatus);
12185 }
12186
12201 @Deprecated
12202 public ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset) throws TskCoreException {
12203 return taggingMgr.addContentTag(content, tagName, comment, beginByteOffset, endByteOffset).getAddedTag();
12204 }
12205
12206 /*
12207 * Deletes a row from the content_tags table in the case database. @param
12208 * tag A ContentTag data transfer object (DTO) for the row to delete.
12209 * @throws TskCoreException
12210 */
12213 try {
12214 // DELETE FROM content_tags WHERE tag_id = ?
12215 PreparedStatement statement = trans.getConnection().getPreparedStatement(PREPARED_STATEMENT.DELETE_CONTENT_TAG);
12216 statement.clearParameters();
12217 statement.setLong(1, tag.getId());
12218 trans.getConnection().executeUpdate(statement);
12219
12220 // update the aggregate score for the content
12221 Long contentId = tag.getContent() != null ? tag.getContent().getId() : null;
12222 Long dataSourceId = tag.getContent() != null && tag.getContent().getDataSource() != null
12223 ? tag.getContent().getDataSource().getId()
12224 : null;
12225
12226 this.getScoringManager().updateAggregateScoreAfterDeletion(contentId, dataSourceId, trans);
12227
12228 trans.commit();
12229 trans = null;
12230 } catch (SQLException ex) {
12231 throw new TskCoreException("Error deleting row from content_tags table (id = " + tag.getId() + ")", ex);
12232 } finally {
12233 if (trans != null) {
12234 trans.rollback();
12235 }
12236 }
12237 }
12238
12247 public List<ContentTag> getAllContentTags() throws TskCoreException {
12248 CaseDbConnection connection = null;
12249 ResultSet resultSet = null;
12251 try {
12252 connection = connections.getConnection();
12253
12254 // 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
12255 // FROM content_tags
12256 // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
12257 // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
12258 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS);
12259 resultSet = connection.executeQuery(statement);
12260 ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
12261 while (resultSet.next()) {
12262 TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12263 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12264 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
12265 Content content = getContentById(resultSet.getLong("obj_id")); //NON-NLS
12266 tags.add(new ContentTag(resultSet.getLong("tag_id"), content, tagName, resultSet.getString("comment"),
12267 resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"))); //NON-NLS
12268 }
12269 return tags;
12270 } catch (SQLException ex) {
12271 throw new TskCoreException("Error selecting rows from content_tags table", ex);
12272 } finally {
12273 closeResultSet(resultSet);
12274 closeConnection(connection);
12276 }
12277 }
12278
12290 if (tagName.getId() == Tag.ID_NOT_SET) {
12291 throw new TskCoreException("TagName object is invalid, id not set");
12292 }
12293 CaseDbConnection connection = null;
12294 ResultSet resultSet = null;
12296 try {
12297 connection = connections.getConnection();
12298
12299 // SELECT COUNT(*) AS count FROM content_tags WHERE tag_name_id = ?
12300 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CONTENT_TAGS_BY_TAG_NAME);
12301 statement.clearParameters();
12302 statement.setLong(1, tagName.getId());
12303 resultSet = connection.executeQuery(statement);
12304 if (resultSet.next()) {
12305 return resultSet.getLong("count");
12306 } else {
12307 throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")");
12308 }
12309 } catch (SQLException ex) {
12310 throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")", ex);
12311 } finally {
12312 closeResultSet(resultSet);
12313 closeConnection(connection);
12315 }
12316 }
12317
12333 public long getContentTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
12334
12335 if (tagName.getId() == Tag.ID_NOT_SET) {
12336 throw new TskCoreException("TagName object is invalid, id not set");
12337 }
12338
12339 CaseDbConnection connection = null;
12340 ResultSet resultSet = null;
12342 try {
12343 connection = connections.getConnection();
12344
12345 // "SELECT COUNT(*) AS count FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id"
12346 // + " AND content_tags.tag_name_id = ? "
12347 // + " AND tsk_files.data_source_obj_id = ? "
12348 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
12349 statement.clearParameters();
12350 statement.setLong(1, tagName.getId());
12351 statement.setLong(2, dsObjId);
12352
12353 resultSet = connection.executeQuery(statement);
12354 if (resultSet.next()) {
12355 return resultSet.getLong("count");
12356 } else {
12357 throw new TskCoreException("Error getting content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")" + " for dsObjId = " + dsObjId);
12358 }
12359 } catch (SQLException ex) {
12360 throw new TskCoreException("Failed to get content_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
12361 } finally {
12362 closeResultSet(resultSet);
12363 closeConnection(connection);
12365 }
12366 }
12367
12378 public ContentTag getContentTagByID(long contentTagID) throws TskCoreException {
12379
12380 CaseDbConnection connection = null;
12381 ResultSet resultSet = null;
12382 ContentTag tag = null;
12384 try {
12385 connection = connections.getConnection();
12386
12387 // 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
12388 // FROM content_tags
12389 // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
12390 // UTER LEFT JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
12391 // WHERE tag_id = ?
12392 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAG_BY_ID);
12393 statement.clearParameters();
12394 statement.setLong(1, contentTagID);
12395 resultSet = connection.executeQuery(statement);
12396
12397 while (resultSet.next()) {
12398 TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12399 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12400 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
12401 tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")), tagName,
12402 resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name"));
12403 }
12404 resultSet.close();
12405
12406 } catch (SQLException ex) {
12407 throw new TskCoreException("Error getting content tag with id = " + contentTagID, ex);
12408 } finally {
12409 closeResultSet(resultSet);
12410 closeConnection(connection);
12412 }
12413 return tag;
12414 }
12415
12427 public List<ContentTag> getContentTagsByTagName(TagName tagName) throws TskCoreException {
12428 if (tagName.getId() == Tag.ID_NOT_SET) {
12429 throw new TskCoreException("TagName object is invalid, id not set");
12430 }
12431 CaseDbConnection connection = null;
12432 ResultSet resultSet = null;
12434 try {
12435 connection = connections.getConnection();
12436
12437 // 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
12438 // FROM content_tags
12439 // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
12440 // WHERE tag_name_id = ?
12441 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_TAG_NAME);
12442 statement.clearParameters();
12443 statement.setLong(1, tagName.getId());
12444 resultSet = connection.executeQuery(statement);
12445 ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
12446 while (resultSet.next()) {
12447 ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")),
12448 tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
12449 tags.add(tag);
12450 }
12451 resultSet.close();
12452 return tags;
12453 } catch (SQLException ex) {
12454 throw new TskCoreException("Error getting content_tags rows (tag_name_id = " + tagName.getId() + ")", ex);
12455 } finally {
12456 closeResultSet(resultSet);
12457 closeConnection(connection);
12459 }
12460 }
12461
12476 public List<ContentTag> getContentTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
12477
12478 CaseDbConnection connection = null;
12479 ResultSet resultSet = null;
12481 try {
12482 connection = connections.getConnection();
12483
12484 // NOTE: Getting all content tags by tag name for a given data source includes
12485 // looking up all Content objects that have entries in tsk_files, as well as
12486 // all OsAccounts. OsAccounts do not have corresponding entries in tsk_files so we
12487 // have to do a separate query to look them up, and then do a UNION of the results.
12488
12489// "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, tag_names.tag_set_id, tsk_examiners.login_name "
12490// + "FROM content_tags "
12491// + "JOIN tsk_os_accounts acc ON content_tags.obj_id = acc.os_account_obj_id "
12492// + "JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
12493// + "JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
12494// + "WHERE content_tags.tag_name_id = ? "
12495// + "AND acc.os_account_obj_id IN (SELECT os_account_obj_id FROM tsk_os_account_instances WHERE data_source_obj_id = ?) "
12496// + "AND acc.db_status = " + OsAccount.OsAccountDbStatus.ACTIVE.getId()
12497// + " UNION "
12498// + "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, tag_names.tag_set_id, tsk_examiners.login_name "
12499// + "FROM content_tags as content_tags, tsk_files as tsk_files, tag_names as tag_names, tsk_examiners as tsk_examiners "
12500// + "WHERE content_tags.examiner_id = tsk_examiners.examiner_id "
12501// + "AND content_tags.obj_id = tsk_files.obj_id "
12502// + "AND content_tags.tag_name_id = tag_names.tag_name_id "
12503// + "AND content_tags.tag_name_id = ? "
12504// + "AND tsk_files.data_source_obj_id = ? "
12505
12506 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
12507 statement.clearParameters();
12508 statement.setLong(1, tagName.getId());
12509 statement.setLong(2, dsObjId);
12510 statement.setLong(3, tagName.getId());
12511 statement.setLong(4, dsObjId);
12512 resultSet = connection.executeQuery(statement);
12513 ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
12514 while (resultSet.next()) {
12515 ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), getContentById(resultSet.getLong("obj_id")),
12516 tagName, resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
12517 tags.add(tag);
12518 }
12519 resultSet.close();
12520 return tags;
12521 } catch (SQLException ex) {
12522 throw new TskCoreException("Failed to get content_tags row count for tag_name_id = " + tagName.getId() + " data source objID : " + dsObjId, ex);
12523 } finally {
12524 closeResultSet(resultSet);
12525 closeConnection(connection);
12527 }
12528 }
12529
12541 public List<ContentTag> getContentTagsByContent(Content content) throws TskCoreException {
12542 CaseDbConnection connection = null;
12543 ResultSet resultSet = null;
12545 try {
12546 connection = connections.getConnection();
12547
12548 // 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
12549 // FROM content_tags
12550 // INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id
12551 // LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id
12552 // WHERE content_tags.obj_id = ?
12553 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_CONTENT_TAGS_BY_CONTENT);
12554 statement.clearParameters();
12555 statement.setLong(1, content.getId());
12556 resultSet = connection.executeQuery(statement);
12557 ArrayList<ContentTag> tags = new ArrayList<ContentTag>();
12558 while (resultSet.next()) {
12559 TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12560 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12561 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
12562 ContentTag tag = new ContentTag(resultSet.getLong("tag_id"), content, tagName,
12563 resultSet.getString("comment"), resultSet.getLong("begin_byte_offset"), resultSet.getLong("end_byte_offset"), resultSet.getString("login_name")); //NON-NLS
12564 tags.add(tag);
12565 }
12566 return tags;
12567 } catch (SQLException ex) {
12568 throw new TskCoreException("Error getting content tags data for content (obj_id = " + content.getId() + ")", ex);
12569 } finally {
12570 closeResultSet(resultSet);
12571 closeConnection(connection);
12573 }
12574 }
12575
12590 @Deprecated
12592 return taggingMgr.addArtifactTag(artifact, tagName, comment).getAddedTag();
12593 }
12594
12595 /*
12596 * Deletes a row from the blackboard_artifact_tags table in the case
12597 * database. @param tag A BlackboardArtifactTag data transfer object (DTO)
12598 * representing the row to delete. @throws TskCoreException
12599 */
12602 try {
12603 // DELETE FROM blackboard_artifact_tags WHERE tag_id = ?
12604 PreparedStatement statement = trans.getConnection().getPreparedStatement(PREPARED_STATEMENT.DELETE_ARTIFACT_TAG);
12605 statement.clearParameters();
12606 statement.setLong(1, tag.getId());
12607 trans.getConnection().executeUpdate(statement);
12608
12609 // update the aggregate score for the artifact
12610 Long artifactObjId = tag.getArtifact().getId();
12611 Long dataSourceId = tag.getContent() != null && tag.getContent().getDataSource() != null
12612 ? tag.getContent().getDataSource().getId()
12613 : null;
12614
12615 this.getScoringManager().updateAggregateScoreAfterDeletion(artifactObjId, dataSourceId, trans);
12616
12617 trans.commit();
12618 trans = null;
12619 } catch (SQLException ex) {
12620 throw new TskCoreException("Error deleting row from blackboard_artifact_tags table (id = " + tag.getId() + ")", ex);
12621 } finally {
12622 if (trans != null) {
12623 trans.rollback();
12624 }
12625 }
12626 }
12627
12637 public List<BlackboardArtifactTag> getAllBlackboardArtifactTags() throws TskCoreException {
12638 CaseDbConnection connection = null;
12639 ResultSet resultSet = null;
12641 try {
12642 connection = connections.getConnection();
12643
12644 // 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
12645 // FROM blackboard_artifact_tags
12646 // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
12647 // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
12648 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS);
12649 resultSet = connection.executeQuery(statement);
12650 ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
12651 while (resultSet.next()) {
12652 TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12653 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12654 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
12655 BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
12656 Content content = getContentById(artifact.getObjectID());
12657 BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
12658 artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
12659 tags.add(tag);
12660 }
12661 return tags;
12662 } catch (SQLException ex) {
12663 throw new TskCoreException("Error selecting rows from blackboard_artifact_tags table", ex);
12664 } finally {
12665 closeResultSet(resultSet);
12666 closeConnection(connection);
12668 }
12669 }
12670
12682 if (tagName.getId() == Tag.ID_NOT_SET) {
12683 throw new TskCoreException("TagName object is invalid, id not set");
12684 }
12685 CaseDbConnection connection = null;
12686 ResultSet resultSet = null;
12688 try {
12689 connection = connections.getConnection();
12690
12691 // SELECT COUNT(*) AS count FROM blackboard_artifact_tags WHERE tag_name_id = ?
12692 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_TAG_NAME);
12693 statement.clearParameters();
12694 statement.setLong(1, tagName.getId());
12695 resultSet = connection.executeQuery(statement);
12696 if (resultSet.next()) {
12697 return resultSet.getLong("count");
12698 } else {
12699 throw new TskCoreException("Error getting blackboard_artifact_tags row count for tag name (tag_name_id = " + tagName.getId() + ")");
12700 }
12701 } catch (SQLException ex) {
12702 throw new TskCoreException("Error getting blackboard artifact_content_tags row count for tag name (tag_name_id = " + tagName.getId() + ")", ex);
12703 } finally {
12704 closeResultSet(resultSet);
12705 closeConnection(connection);
12707 }
12708 }
12709
12724 public long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId) throws TskCoreException {
12725
12726 if (tagName.getId() == Tag.ID_NOT_SET) {
12727 throw new TskCoreException("TagName object is invalid, id not set");
12728 }
12729
12730 CaseDbConnection connection = null;
12731 ResultSet resultSet = null;
12733 try {
12734 connection = connections.getConnection();
12735
12736 // "SELECT COUNT(*) AS count FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts WHERE artifact_tags.artifact_id = arts.artifact_id"
12737 // + " AND artifact_tags.tag_name_id = ?"
12738 // + " AND arts.data_source_obj_id = ? "
12739 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.COUNT_ARTIFACTS_BY_TAG_NAME_BY_DATASOURCE);
12740 statement.clearParameters();
12741 statement.setLong(1, tagName.getId());
12742 statement.setLong(2, dsObjId);
12743 resultSet = connection.executeQuery(statement);
12744 if (resultSet.next()) {
12745 return resultSet.getLong("count");
12746 } else {
12747 throw new TskCoreException("Error getting blackboard_artifact_tags row count for tag name (tag_name_id = " + tagName.getId() + ")" + " for dsObjId = " + dsObjId);
12748 }
12749 } catch (SQLException ex) {
12750 throw new TskCoreException("Failed to get blackboard_artifact_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
12751 } finally {
12752 closeResultSet(resultSet);
12753 closeConnection(connection);
12755 }
12756 }
12757
12769 public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName) throws TskCoreException {
12770 if (tagName.getId() == Tag.ID_NOT_SET) {
12771 throw new TskCoreException("TagName object is invalid, id not set");
12772 }
12773 CaseDbConnection connection = null;
12774 ResultSet resultSet = null;
12776 try {
12777 connection = connections.getConnection();
12778
12779 // 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
12780 // FROM blackboard_artifact_tags
12781 // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
12782 // WHERE tag_name_id = ?
12783 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_TAG_NAME);
12784 statement.clearParameters();
12785 statement.setLong(1, tagName.getId());
12786 resultSet = connection.executeQuery(statement);
12787 ArrayList<BlackboardArtifactTag> tags = new ArrayList<BlackboardArtifactTag>();
12788 while (resultSet.next()) {
12789 BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
12790 Content content = getContentById(artifact.getObjectID());
12791 BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
12792 artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
12793 tags.add(tag);
12794 }
12795 return tags;
12796 } catch (SQLException ex) {
12797 throw new TskCoreException("Error getting blackboard artifact tags data (tag_name_id = " + tagName.getId() + ")", ex);
12798 } finally {
12799 closeResultSet(resultSet);
12800 closeConnection(connection);
12802 }
12803 }
12804
12819 public List<BlackboardArtifactTag> getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId) throws TskCoreException {
12820
12821 if (tagName.getId() == Tag.ID_NOT_SET) {
12822 throw new TskCoreException("TagName object is invalid, id not set");
12823 }
12824
12825 CaseDbConnection connection = null;
12826 ResultSet resultSet = null;
12828 try {
12829 connection = connections.getConnection();
12830
12831 // 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
12832 // FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts
12833 // LEFT OUTER JOIN tsk_examiners ON artifact_tags.examiner_id = tsk_examiners.examiner_id
12834 // WHERE artifact_tags.artifact_id = arts.artifact_id
12835 // AND artifact_tags.tag_name_id = ?
12836 // AND arts.data_source_obj_id = ?
12837 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_TAG_NAME_BY_DATASOURCE);
12838 statement.clearParameters();
12839 statement.setLong(1, tagName.getId());
12840 statement.setLong(2, dsObjId);
12841 resultSet = connection.executeQuery(statement);
12842 ArrayList<BlackboardArtifactTag> tags = new ArrayList<BlackboardArtifactTag>();
12843 while (resultSet.next()) {
12844 BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
12845 Content content = getContentById(artifact.getObjectID());
12846 BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
12847 artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
12848 tags.add(tag);
12849 }
12850 return tags;
12851 } catch (SQLException ex) {
12852 throw new TskCoreException("Failed to get blackboard_artifact_tags row count for tag_name_id = " + tagName.getId() + "data source objID : " + dsObjId, ex);
12853 } finally {
12854 closeResultSet(resultSet);
12855 closeConnection(connection);
12857 }
12858
12859 }
12860
12873
12874 CaseDbConnection connection = null;
12875 ResultSet resultSet = null;
12876 BlackboardArtifactTag tag = null;
12878 try {
12879 connection = connections.getConnection();
12880
12881 //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
12882 // FROM blackboard_artifact_tags
12883 // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
12884 // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
12885 // WHERE blackboard_artifact_tags.tag_id = ?
12886 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAG_BY_ID);
12887 statement.clearParameters();
12888 statement.setLong(1, artifactTagID);
12889 resultSet = connection.executeQuery(statement);
12890
12891 while (resultSet.next()) {
12892 TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12893 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12894 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank"));
12895 BlackboardArtifact artifact = getBlackboardArtifact(resultSet.getLong("artifact_id")); //NON-NLS
12896 Content content = getContentById(artifact.getObjectID());
12897 tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
12898 artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name"));
12899 }
12900 resultSet.close();
12901
12902 } catch (SQLException ex) {
12903 throw new TskCoreException("Error getting blackboard artifact tag with id = " + artifactTagID, ex);
12904 } finally {
12905 closeResultSet(resultSet);
12906 closeConnection(connection);
12908 }
12909 return tag;
12910 }
12911
12924 public List<BlackboardArtifactTag> getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact) throws TskCoreException {
12925 CaseDbConnection connection = null;
12926 ResultSet resultSet = null;
12928 try {
12929 connection = connections.getConnection();
12930
12931 // 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
12932 // FROM blackboard_artifact_tags
12933 // INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id
12934 // LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id
12935 // WHERE blackboard_artifact_tags.artifact_id = ?
12936 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_ARTIFACT_TAGS_BY_ARTIFACT);
12937 statement.clearParameters();
12938 statement.setLong(1, artifact.getArtifactID());
12939 resultSet = connection.executeQuery(statement);
12940 ArrayList<BlackboardArtifactTag> tags = new ArrayList<>();
12941 while (resultSet.next()) {
12942 TagName tagName = new TagName(resultSet.getLong("tag_name_id"), resultSet.getString("display_name"),
12943 resultSet.getString("description"), TagName.HTML_COLOR.getColorByName(resultSet.getString("color")),
12944 TskData.TagType.valueOf(resultSet.getByte("knownStatus")), resultSet.getLong("tag_set_id"), resultSet.getInt("rank")); //NON-NLS
12945 Content content = getContentById(artifact.getObjectID());
12946 BlackboardArtifactTag tag = new BlackboardArtifactTag(resultSet.getLong("tag_id"),
12947 artifact, content, tagName, resultSet.getString("comment"), resultSet.getString("login_name")); //NON-NLS
12948 tags.add(tag);
12949 }
12950 return tags;
12951 } catch (SQLException ex) {
12952 throw new TskCoreException("Error getting blackboard artifact tags data (artifact_id = " + artifact.getArtifactID() + ")", ex);
12953 } finally {
12954 closeResultSet(resultSet);
12955 closeConnection(connection);
12957 }
12958 }
12959
12968 public void updateImagePath(String newPath, long objectId) throws TskCoreException {
12970 try (CaseDbConnection connection = connections.getConnection();) {
12971 // UPDATE tsk_image_names SET name = ? WHERE obj_id = ?
12972 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.UPDATE_IMAGE_PATH);
12973 statement.clearParameters();
12974 statement.setString(1, newPath);
12975 statement.setLong(2, objectId);
12976 connection.executeUpdate(statement);
12977 } catch (SQLException ex) {
12978 throw new TskCoreException("Error updating image path in database for object " + objectId, ex);
12979 } finally {
12981 }
12982 }
12983
12997 public Report addReport(String localPath, String sourceModuleName, String reportName) throws TskCoreException {
12998 return addReport(localPath, sourceModuleName, reportName, null);
12999 }
13000
13016 public Report addReport(String localPath, String sourceModuleName, String reportName, Content parent) throws TskCoreException {
13017 // Make sure the local path of the report is in the database directory
13018 // or one of its subdirectories.
13019 String relativePath = ""; //NON-NLS
13020 long createTime = 0;
13021 String localPathLower = localPath.toLowerCase();
13022
13023 if (localPathLower.startsWith("http")) {
13024 relativePath = localPathLower;
13025 createTime = System.currentTimeMillis() / 1000;
13026 } else {
13027 /*
13028 * Note: The following call to .relativize() may be dangerous in
13029 * case-sensitive operating systems and should be looked at. For
13030 * now, we are simply relativizing the paths as all lower case, then
13031 * using the length of the result to pull out the appropriate number
13032 * of characters from the localPath String.
13033 */
13034 try {
13035 String casePathLower = getDbDirPath().toLowerCase();
13036 int length = new File(casePathLower).toURI().relativize(new File(localPathLower).toURI()).getPath().length();
13037 relativePath = new File(localPath.substring(localPathLower.length() - length)).getPath();
13038 } catch (IllegalArgumentException ex) {
13039 String errorMessage = String.format("Local path %s not in the database directory or one of its subdirectories", localPath);
13040 throw new TskCoreException(errorMessage, ex);
13041 }
13042 try {
13043 // get its file time
13044 java.io.File tempFile = new java.io.File(localPath);
13045 // Convert to UNIX epoch (seconds, not milliseconds).
13046 createTime = tempFile.lastModified() / 1000;
13047 } catch (Exception ex) {
13048 throw new TskCoreException("Could not get create time for report at " + localPath, ex);
13049 }
13050 }
13051
13052 // Write the report data to the database.
13054 try (CaseDbConnection connection = connections.getConnection();) {
13055 // Insert a row for the report into the tsk_objects table.
13056 // INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)
13057 long parentObjId = 0;
13058 if (parent != null) {
13059 parentObjId = parent.getId();
13060 }
13061 long objectId = addObject(parentObjId, TskData.ObjectType.REPORT.getObjectType(), connection);
13062
13063 // INSERT INTO reports (obj_id, path, crtime, src_module_name, display_name) VALUES (?, ?, ?, ?, ?)
13064 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_REPORT);
13065 statement.clearParameters();
13066 statement.setLong(1, objectId);
13067 statement.setString(2, relativePath);
13068 statement.setLong(3, createTime);
13069 statement.setString(4, sourceModuleName);
13070 statement.setString(5, reportName);
13071 connection.executeUpdate(statement);
13072 return new Report(this, objectId, localPath, createTime, sourceModuleName, reportName, parent);
13073 } catch (SQLException ex) {
13074 throw new TskCoreException("Error adding report " + localPath + " to reports table", ex);
13075 } finally {
13077 }
13078 }
13079
13088 public List<Report> getAllReports() throws TskCoreException {
13089 CaseDbConnection connection = null;
13090 ResultSet resultSet = null;
13091 ResultSet parentResultSet = null;
13092 PreparedStatement statement = null;
13093 Statement parentStatement = null;
13095 try {
13096 connection = connections.getConnection();
13097
13098 // SELECT * FROM reports
13099 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_REPORTS);
13100 parentStatement = connection.createStatement();
13101 resultSet = connection.executeQuery(statement);
13102 ArrayList<Report> reports = new ArrayList<Report>();
13103 while (resultSet.next()) {
13104 String localpath = resultSet.getString("path");
13105 if (localpath.toLowerCase().startsWith("http") == false) {
13106 // make path absolute
13107 localpath = Paths.get(getDbDirPath(), localpath).normalize().toString(); //NON-NLS
13108 }
13109
13110 // get the report parent
13111 Content parent = null;
13112 long reportId = resultSet.getLong("obj_id"); // NON-NLS
13113 String parentQuery = String.format("SELECT * FROM tsk_objects WHERE obj_id = %s;", reportId);
13114 parentResultSet = parentStatement.executeQuery(parentQuery);
13115 if (parentResultSet.next()) {
13116 long parentId = parentResultSet.getLong("par_obj_id"); // NON-NLS
13117 parent = this.getContentById(parentId);
13118 }
13119 parentResultSet.close();
13120
13121 reports.add(new Report(this,
13122 reportId,
13123 localpath,
13124 resultSet.getLong("crtime"), //NON-NLS
13125 resultSet.getString("src_module_name"), //NON-NLS
13126 resultSet.getString("report_name"),
13127 parent)); //NON-NLS
13128 }
13129 return reports;
13130 } catch (SQLException ex) {
13131 throw new TskCoreException("Error querying reports table", ex);
13132 } finally {
13133 closeResultSet(resultSet);
13134 closeResultSet(parentResultSet);
13135 closeStatement(statement);
13136 closeStatement(parentStatement);
13137
13138 closeConnection(connection);
13140 }
13141 }
13142
13152 public Report getReportById(long id) throws TskCoreException {
13153 CaseDbConnection connection = null;
13154 PreparedStatement statement = null;
13155 Statement parentStatement = null;
13156 ResultSet resultSet = null;
13157 ResultSet parentResultSet = null;
13158 Report report = null;
13160 try {
13161 connection = connections.getConnection();
13162
13163 // SELECT * FROM reports WHERE obj_id = ?
13164 statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_REPORT_BY_ID);
13165 parentStatement = connection.createStatement();
13166 statement.clearParameters();
13167 statement.setLong(1, id);
13168 resultSet = connection.executeQuery(statement);
13169
13170 if (resultSet.next()) {
13171 // get the report parent
13172 Content parent = null;
13173 String parentQuery = String.format("SELECT * FROM tsk_objects WHERE obj_id = %s;", id);
13174 parentResultSet = parentStatement.executeQuery(parentQuery);
13175 if (parentResultSet.next()) {
13176 long parentId = parentResultSet.getLong("par_obj_id"); // NON-NLS
13177 parent = this.getContentById(parentId);
13178 }
13179
13180 report = new Report(this, resultSet.getLong("obj_id"), //NON-NLS
13181 Paths.get(getDbDirPath(), resultSet.getString("path")).normalize().toString(), //NON-NLS
13182 resultSet.getLong("crtime"), //NON-NLS
13183 resultSet.getString("src_module_name"), //NON-NLS
13184 resultSet.getString("report_name"),
13185 parent); //NON-NLS
13186 } else {
13187 throw new TskCoreException("No report found for id: " + id);
13188 }
13189 } catch (SQLException ex) {
13190 throw new TskCoreException("Error querying reports table for id: " + id, ex);
13191 } finally {
13192 closeResultSet(resultSet);
13193 closeResultSet(parentResultSet);
13194 closeStatement(statement);
13195 closeStatement(parentStatement);
13196 closeConnection(connection);
13198 }
13199
13200 return report;
13201 }
13202
13210 public void deleteReport(Report report) throws TskCoreException {
13212 try (CaseDbConnection connection = connections.getConnection();) {
13213 // DELETE FROM reports WHERE reports.obj_id = ?
13214 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_REPORT);
13215 statement.setLong(1, report.getId());
13216 connection.executeUpdate(statement);
13217 // DELETE FROM tsk_objects WHERE tsk_objects.obj_id = ?
13218 statement = connection.getPreparedStatement(PREPARED_STATEMENT.DELETE_REPORT_TSK_OBJECT);
13219 statement.setLong(1, report.getId());
13220 statement.setLong(2, TskData.ObjectType.REPORT.getObjectType());
13221 connection.executeUpdate(statement);
13222 } catch (SQLException ex) {
13223 throw new TskCoreException("Error querying reports table", ex);
13224 } finally {
13226 }
13227 }
13228
13229 static void closeResultSet(ResultSet resultSet) {
13230 if (resultSet != null) {
13231 try {
13232 resultSet.close();
13233 } catch (SQLException ex) {
13234 logger.log(Level.SEVERE, "Error closing ResultSet", ex); //NON-NLS
13235 }
13236 }
13237 }
13238
13239 static void closeStatement(Statement statement) {
13240 if (statement != null) {
13241 try {
13242 statement.close();
13243 } catch (SQLException ex) {
13244 logger.log(Level.SEVERE, "Error closing Statement", ex); //NON-NLS
13245
13246 }
13247 }
13248 }
13249
13250 static void closeConnection(CaseDbConnection connection) {
13251 if (connection != null) {
13252 connection.close();
13253 }
13254 }
13255
13256 private static void rollbackTransaction(CaseDbConnection connection) {
13257 if (connection != null) {
13258 connection.rollbackTransaction();
13259 }
13260 }
13261
13270 void setIngestJobEndDateTime(long ingestJobId, long endDateTime) throws TskCoreException {
13272 try (CaseDbConnection connection = connections.getConnection();) {
13273 Statement statement = connection.createStatement();
13274 statement.executeUpdate("UPDATE ingest_jobs SET end_date_time=" + endDateTime + " WHERE ingest_job_id=" + ingestJobId + ";");
13275 } catch (SQLException ex) {
13276 throw new TskCoreException("Error updating the end date (ingest_job_id = " + ingestJobId + ".", ex);
13277 } finally {
13279 }
13280 }
13281
13282 void setIngestJobStatus(long ingestJobId, IngestJobStatusType status) throws TskCoreException {
13284 try (CaseDbConnection connection = connections.getConnection();
13285 Statement statement = connection.createStatement();) {
13286 statement.executeUpdate("UPDATE ingest_jobs SET status_id=" + status.ordinal() + " WHERE ingest_job_id=" + ingestJobId + ";");
13287 } catch (SQLException ex) {
13288 throw new TskCoreException("Error ingest job status (ingest_job_id = " + ingestJobId + ".", ex);
13289 } finally {
13291 }
13292 }
13293
13310 public final IngestJobInfo addIngestJob(Content dataSource, String hostName, List<IngestModuleInfo> ingestModules, Date jobStart, Date jobEnd, IngestJobStatusType status, String settingsDir) throws TskCoreException {
13311 CaseDbConnection connection = null;
13313 ResultSet resultSet = null;
13314 Statement statement;
13315 try {
13316 connection = connections.getConnection();
13317 connection.beginTransaction();
13318 statement = connection.createStatement();
13319 PreparedStatement insertStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INGEST_JOB, Statement.RETURN_GENERATED_KEYS);
13320 insertStatement.setLong(1, dataSource.getId());
13321 insertStatement.setString(2, hostName);
13322 insertStatement.setLong(3, jobStart.getTime());
13323 insertStatement.setLong(4, jobEnd.getTime());
13324 insertStatement.setInt(5, status.ordinal());
13325 insertStatement.setString(6, settingsDir);
13326 connection.executeUpdate(insertStatement);
13327 resultSet = insertStatement.getGeneratedKeys();
13328 resultSet.next();
13329 long id = resultSet.getLong(1); //last_insert_rowid()
13330 for (int i = 0; i < ingestModules.size(); i++) {
13331 IngestModuleInfo ingestModule = ingestModules.get(i);
13332 statement.executeUpdate("INSERT INTO ingest_job_modules (ingest_job_id, ingest_module_id, pipeline_position) "
13333 + "VALUES (" + id + ", " + ingestModule.getIngestModuleId() + ", " + i + ");");
13334 }
13335 resultSet.close();
13336 resultSet = null;
13337 connection.commitTransaction();
13338 return new IngestJobInfo(id, dataSource.getId(), hostName, jobStart, "", ingestModules, this);
13339 } catch (SQLException ex) {
13340 rollbackTransaction(connection);
13341 throw new TskCoreException("Error adding the ingest job.", ex);
13342 } finally {
13343 closeResultSet(resultSet);
13344 closeConnection(connection);
13346 }
13347 }
13348
13362 public final IngestModuleInfo addIngestModule(String displayName, String factoryClassName, IngestModuleType type, String version) throws TskCoreException {
13363 CaseDbConnection connection = null;
13364 ResultSet resultSet = null;
13365 Statement statement = null;
13366 String uniqueName = factoryClassName + "-" + displayName + "-" + version;
13368 try {
13369 connection = connections.getConnection();
13370 statement = connection.createStatement();
13371 resultSet = statement.executeQuery("SELECT * FROM ingest_modules WHERE unique_name = '" + uniqueName + "'");
13372 if (!resultSet.next()) {
13373 resultSet.close();
13374 resultSet = null;
13375 PreparedStatement insertStatement = connection.getPreparedStatement(PREPARED_STATEMENT.INSERT_INGEST_MODULE, Statement.RETURN_GENERATED_KEYS);
13376 insertStatement.setString(1, displayName);
13377 insertStatement.setString(2, uniqueName);
13378 insertStatement.setInt(3, type.ordinal());
13379 insertStatement.setString(4, version);
13380 connection.executeUpdate(insertStatement);
13381 resultSet = insertStatement.getGeneratedKeys();
13382 resultSet.next();
13383 long id = resultSet.getLong(1); //last_insert_rowid()
13384 resultSet.close();
13385 resultSet = null;
13386 return new IngestModuleInfo(id, displayName, uniqueName, type, version);
13387 } else {
13388 return new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
13389 resultSet.getString("unique_name"), IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version"));
13390 }
13391 } catch (SQLException ex) {
13392 try {
13393 closeStatement(statement);
13394 if (connection != null) {
13395 statement = connection.createStatement();
13396 resultSet = statement.executeQuery("SELECT * FROM ingest_modules WHERE unique_name = '" + uniqueName + "'");
13397 if (resultSet.next()) {
13398 return new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
13399 uniqueName, IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version"));
13400 }
13401 }
13402 throw new TskCoreException("Couldn't add new module to database.", ex);
13403 } catch (SQLException ex1) {
13404 throw new TskCoreException("Couldn't add new module to database.", ex1);
13405 }
13406 } finally {
13407 closeResultSet(resultSet);
13408 closeStatement(statement);
13409 closeConnection(connection);
13411 }
13412 }
13413
13421 public final List<IngestJobInfo> getIngestJobs() throws TskCoreException {
13422 CaseDbConnection connection = null;
13423 ResultSet resultSet = null;
13424 Statement statement = null;
13425 List<IngestJobInfo> ingestJobs = new ArrayList<>();
13427 try {
13428 connection = connections.getConnection();
13429 statement = connection.createStatement();
13430 resultSet = statement.executeQuery("SELECT * FROM ingest_jobs");
13431 while (resultSet.next()) {
13432 ingestJobs.add(new IngestJobInfo(resultSet.getInt("ingest_job_id"), resultSet.getLong("obj_id"),
13433 resultSet.getString("host_name"), new Date(resultSet.getLong("start_date_time")),
13434 new Date(resultSet.getLong("end_date_time")), IngestJobStatusType.fromID(resultSet.getInt("status_id")),
13435 resultSet.getString("settings_dir"), this.getIngestModules(resultSet.getInt("ingest_job_id"), connection), this));
13436 }
13437 return ingestJobs;
13438 } catch (SQLException ex) {
13439 throw new TskCoreException("Couldn't get the ingest jobs.", ex);
13440 } finally {
13441 closeResultSet(resultSet);
13442 closeStatement(statement);
13443 closeConnection(connection);
13445 }
13446 }
13447
13458 private List<IngestModuleInfo> getIngestModules(int ingestJobId, CaseDbConnection connection) throws SQLException {
13459 ResultSet resultSet = null;
13460 Statement statement = null;
13461 List<IngestModuleInfo> ingestModules = new ArrayList<>();
13463 try {
13464 statement = connection.createStatement();
13465 resultSet = statement.executeQuery("SELECT ingest_job_modules.ingest_module_id AS ingest_module_id, "
13466 + "ingest_job_modules.pipeline_position AS pipeline_position, "
13467 + "ingest_modules.display_name AS display_name, ingest_modules.unique_name AS unique_name, "
13468 + "ingest_modules.type_id AS type_id, ingest_modules.version AS version "
13469 + "FROM ingest_job_modules, ingest_modules "
13470 + "WHERE ingest_job_modules.ingest_job_id = " + ingestJobId + " "
13471 + "AND ingest_modules.ingest_module_id = ingest_job_modules.ingest_module_id "
13472 + "ORDER BY (ingest_job_modules.pipeline_position);");
13473 while (resultSet.next()) {
13474 ingestModules.add(new IngestModuleInfo(resultSet.getInt("ingest_module_id"), resultSet.getString("display_name"),
13475 resultSet.getString("unique_name"), IngestModuleType.fromID(resultSet.getInt("type_id")), resultSet.getString("version")));
13476 }
13477 return ingestModules;
13478 } finally {
13479 closeResultSet(resultSet);
13480 closeStatement(statement);
13482
13483 }
13484 }
13485
13495 String getInsertOrIgnoreSQL(String sql) {
13496 switch (getDatabaseType()) {
13497 case POSTGRESQL:
13498 return " INSERT " + sql + " ON CONFLICT DO NOTHING "; //NON-NLS
13499 case SQLITE:
13500 return " INSERT OR IGNORE " + sql; //NON-NLS
13501 default:
13502 throw new UnsupportedOperationException("Unsupported DB type: " + getDatabaseType().name());
13503 }
13504 }
13505
13526 private List<? extends BlackboardArtifact> getArtifactsForValues(BlackboardArtifact.Category category, String dbColumn, List<? extends Number> values, CaseDbConnection connection) throws TskCoreException {
13527 String where = "";
13528 // This look creates the OR statement with the following format:
13529 // <dbColumn> = <value> OR <dbColumn> = <value2> OR ...
13530 for (Number value : values) {
13531 if (!where.isEmpty()) {
13532 where += " OR ";
13533 }
13534 where += dbColumn + " = " + value;
13535 }
13536
13537 // Base on the category pass the OR statement to the approprate method
13538 // that will retrieve the artifacts.
13539 if (category == BlackboardArtifact.Category.DATA_ARTIFACT) {
13540 return blackboard.getDataArtifactsWhere(where, connection);
13541 } else {
13542 return blackboard.getAnalysisResultsWhere(where, connection);
13543 }
13544 }
13545
13549 static class ObjectInfo {
13550
13551 private long id;
13552 private TskData.ObjectType type;
13553
13554 ObjectInfo(long id, ObjectType type) {
13555 this.id = id;
13556 this.type = type;
13557 }
13558
13559 long getId() {
13560 return id;
13561 }
13562
13563 TskData.ObjectType getType() {
13564 return type;
13565 }
13566 }
13567
13568 private interface DbCommand {
13569
13570 void execute() throws SQLException;
13571 }
13572
13573 private enum PREPARED_STATEMENT {
13574
13575 SELECT_ARTIFACTS_BY_TYPE("SELECT artifact_id, obj_id FROM blackboard_artifacts " //NON-NLS
13576 + "WHERE artifact_type_id = ?"), //NON-NLS
13577 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
13578 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
13579 COUNT_ARTIFACTS_FROM_SOURCE("SELECT COUNT(*) AS count FROM blackboard_artifacts WHERE obj_id = ? AND review_status_id != " + BlackboardArtifact.ReviewStatus.REJECTED.getID()), //NON-NLS
13580 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
13581 SELECT_FILES_BY_PARENT("SELECT tsk_files.* " //NON-NLS
13582 + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
13583 + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
13584 + "WHERE (tsk_objects.par_obj_id = ? ) " //NON-NLS
13585 + "ORDER BY tsk_files.meta_type DESC, LOWER(tsk_files.name)"), //NON-NLS
13586 SELECT_FILES_BY_PARENT_AND_TYPE("SELECT tsk_files.* " //NON-NLS
13587 + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
13588 + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
13589 + "WHERE (tsk_objects.par_obj_id = ? AND tsk_files.type = ? ) " //NON-NLS
13590 + "ORDER BY tsk_files.dir_type, LOWER(tsk_files.name)"), //NON-NLS
13591 SELECT_FILES_BY_PARENT_AND_NAME("SELECT tsk_files.* " //NON-NLS
13592 + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
13593 + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
13594 + "WHERE (tsk_objects.par_obj_id = ? AND " //NON-NLS
13595 + "LOWER(tsk_files.name) LIKE LOWER(?) AND LOWER(tsk_files.name) NOT LIKE LOWER('%journal%')) "//NON-NLS
13596 + "ORDER BY tsk_files.dir_type, LOWER(tsk_files.name)"), //NON-NLS
13598 + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
13599 + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
13600 + "WHERE tsk_files.extension = ? AND "
13601 + "(tsk_objects.par_obj_id = ? AND " //NON-NLS
13602 + "LOWER(tsk_files.name) LIKE LOWER(?) AND LOWER(tsk_files.name) NOT LIKE LOWER('%journal%')) "//NON-NLS
13603 + "ORDER BY tsk_files.dir_type, LOWER(tsk_files.name)"), //NON-NLS
13604 SELECT_FILE_IDS_BY_PARENT("SELECT tsk_files.obj_id AS obj_id " //NON-NLS
13605 + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
13606 + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
13607 + "WHERE (tsk_objects.par_obj_id = ?)"), //NON-NLS
13608 SELECT_FILE_IDS_BY_PARENT_AND_TYPE("SELECT tsk_files.obj_id AS obj_id " //NON-NLS
13609 + "FROM tsk_objects INNER JOIN tsk_files " //NON-NLS
13610 + "ON tsk_objects.obj_id=tsk_files.obj_id " //NON-NLS
13611 + "WHERE (tsk_objects.par_obj_id = ? " //NON-NLS
13612 + "AND tsk_files.type = ? )"), //NON-NLS
13613 SELECT_FILE_BY_ID("SELECT * FROM tsk_files WHERE obj_id = ? LIMIT 1"), //NON-NLS
13614 SELECT_ARTIFACT_BY_ARTIFACT_OBJ_ID("SELECT * FROM blackboard_artifacts WHERE artifact_obj_id = ? LIMIT 1"),
13615 SELECT_ARTIFACT_TYPE_BY_ARTIFACT_OBJ_ID("SELECT artifact_type_id FROM blackboard_artifacts WHERE artifact_obj_id = ? LIMIT 1"),
13616 SELECT_ARTIFACT_BY_ARTIFACT_ID("SELECT * FROM blackboard_artifacts WHERE artifact_id = ? LIMIT 1"),
13617 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
13618 + "VALUES (?, ?, ?, ?, ?," + BlackboardArtifact.ReviewStatus.UNDECIDED.getID() + ")"), //NON-NLS
13619 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
13620 + "VALUES (DEFAULT, ?, ?, ?, ?," + BlackboardArtifact.ReviewStatus.UNDECIDED.getID() + ")"), //NON-NLS
13621 INSERT_ANALYSIS_RESULT("INSERT INTO tsk_analysis_results (artifact_obj_id, conclusion, significance, priority, configuration, justification) " //NON-NLS
13622 + "VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
13623 INSERT_STRING_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_text) " //NON-NLS
13624 + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
13625 INSERT_BYTE_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_byte) " //NON-NLS
13626 + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
13627 INSERT_INT_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_int32) " //NON-NLS
13628 + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
13629 INSERT_LONG_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_int64) " //NON-NLS
13630 + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
13631 INSERT_DOUBLE_ATTRIBUTE("INSERT INTO blackboard_attributes (artifact_id, artifact_type_id, source, context, attribute_type_id, value_type, value_double) " //NON-NLS
13632 + "VALUES (?,?,?,?,?,?,?)"), //NON-NLS
13633 INSERT_FILE_ATTRIBUTE("INSERT INTO tsk_file_attributes (obj_id, attribute_type_id, value_type, value_byte, value_text, value_int32, value_int64, value_double) " //NON-NLS
13634 + "VALUES (?,?,?,?,?,?,?,?)"), //NON-NLS
13635 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
13636 SELECT_FILES_BY_EXTENSION_AND_DATA_SOURCE_AND_NAME("SELECT * FROM tsk_files WHERE extension = ? AND LOWER(name) LIKE LOWER(?) AND LOWER(name) NOT LIKE LOWER('%journal%') AND data_source_obj_id = ?"), //NON-NLS
13637 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
13638 SELECT_FILES_BY_EXTENSION_AND_DATA_SOURCE_AND_PARENT_PATH_AND_NAME("SELECT * FROM tsk_files WHERE extension = ? AND LOWER(name) LIKE LOWER(?) AND LOWER(name) NOT LIKE LOWER('%journal%') AND LOWER(parent_path) LIKE LOWER(?) AND data_source_obj_id = ?"), //NON-NLS
13639 UPDATE_FILE_MD5("UPDATE tsk_files SET md5 = ? WHERE obj_id = ?"), //NON-NLS
13640 UPDATE_IMAGE_MD5("UPDATE tsk_image_info SET md5 = ? WHERE obj_id = ?"), //NON-NLS
13641 UPDATE_IMAGE_SHA1("UPDATE tsk_image_info SET sha1 = ? WHERE obj_id = ?"), //NON-NLS
13642 UPDATE_IMAGE_SHA256("UPDATE tsk_image_info SET sha256 = ? WHERE obj_id = ?"), //NON-NLS
13643 SELECT_IMAGE_MD5("SELECT md5 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
13644 SELECT_IMAGE_SHA1("SELECT sha1 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
13645 SELECT_IMAGE_SHA256("SELECT sha256 FROM tsk_image_info WHERE obj_id = ?"), //NON-NLS
13646 UPDATE_ACQUISITION_DETAILS("UPDATE data_source_info SET acquisition_details = ? WHERE obj_id = ?"), //NON-NLS
13647 UPDATE_ACQUISITION_TOOL_SETTINGS("UPDATE data_source_info SET acquisition_tool_settings = ?, acquisition_tool_name = ?, acquisition_tool_version = ? WHERE obj_id = ?"), //NON-NLS
13648 SELECT_ACQUISITION_DETAILS("SELECT acquisition_details FROM data_source_info WHERE obj_id = ?"), //NON-NLS
13649 SELECT_ACQUISITION_TOOL_SETTINGS("SELECT acquisition_tool_settings, acquisition_tool_name, acquisition_tool_version, added_date_time FROM data_source_info WHERE obj_id = ?"), //NON-NLS
13650 SELECT_LOCAL_PATH_FOR_FILE("SELECT path FROM tsk_files_path WHERE obj_id = ?"), //NON-NLS
13651 SELECT_ENCODING_FOR_FILE("SELECT encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON-NLS
13652 SELECT_LOCAL_PATH_AND_ENCODING_FOR_FILE("SELECT path, encoding_type FROM tsk_files_path WHERE obj_id = ?"), // NON_NLS
13653 SELECT_PATH_FOR_FILE("SELECT parent_path FROM tsk_files WHERE obj_id = ?"), //NON-NLS
13654 SELECT_FILE_NAME("SELECT name FROM tsk_files WHERE obj_id = ?"), //NON-NLS
13655 SELECT_DERIVED_FILE("SELECT derived_id, rederive FROM tsk_files_derived WHERE obj_id = ?"), //NON-NLS
13656 SELECT_FILE_DERIVATION_METHOD("SELECT tool_name, tool_version, other FROM tsk_files_derived_method WHERE derived_id = ?"), //NON-NLS
13657 SELECT_MAX_OBJECT_ID("SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects"), //NON-NLS
13658 INSERT_OBJECT("INSERT INTO tsk_objects (par_obj_id, type) VALUES (?, ?)"), //NON-NLS
13659 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, sha1, known, mime_type, parent_path, data_source_obj_id, extension, owner_uid, os_account_obj_id, collected) " //NON-NLS
13660 + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), //NON-NLS
13661 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, md5, sha256, sha1, mime_type, parent_path, extension, owner_uid, os_account_obj_id, collected)"
13662 + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"), // NON-NLS
13663 UPDATE_DERIVED_FILE("UPDATE tsk_files SET type = ?, dir_type = ?, meta_type = ?, dir_flags = ?, meta_flags = ?, size= ?, ctime= ?, crtime= ?, atime= ?, mtime= ?, mime_type = ? "
13664 + "WHERE obj_id = ?"), //NON-NLS
13665 INSERT_LAYOUT_FILE("INSERT INTO tsk_file_layout (obj_id, byte_start, byte_len, sequence) " //NON-NLS
13666 + "VALUES (?, ?, ?, ?)"), //NON-NLS
13667 INSERT_LOCAL_PATH("INSERT INTO tsk_files_path (obj_id, path, encoding_type) VALUES (?, ?, ?)"), //NON-NLS
13668 UPDATE_LOCAL_PATH("UPDATE tsk_files_path SET path = ?, encoding_type = ? WHERE obj_id = ?"), //NON-NLS
13669 COUNT_CHILD_OBJECTS_BY_PARENT("SELECT COUNT(obj_id) AS count FROM tsk_objects WHERE par_obj_id = ?"), //NON-NLS
13670 SELECT_FILE_SYSTEM_BY_OBJECT("SELECT fs_obj_id from tsk_files WHERE obj_id=?"), //NON-NLS
13671 SELECT_TAG_NAMES("SELECT * FROM tag_names"), //NON-NLS
13672 SELECT_TAG_NAMES_IN_USE("SELECT * FROM tag_names " //NON-NLS
13673 + "WHERE tag_name_id IN " //NON-NLS
13674 + "(SELECT tag_name_id from content_tags UNION SELECT tag_name_id FROM blackboard_artifact_tags)"), //NON-NLS
13675 SELECT_TAG_NAMES_IN_USE_BY_DATASOURCE("SELECT * FROM tag_names "
13676 + "WHERE tag_name_id IN "
13677 + "( SELECT content_tags.tag_name_id as tag_name_id "
13678 + "FROM content_tags as content_tags, tsk_files as tsk_files"
13679 + " WHERE content_tags.obj_id = tsk_files.obj_id"
13680 + " AND tsk_files.data_source_obj_id = ?"
13681 + " UNION "
13682 + "SELECT artifact_tags.tag_name_id as tag_name_id "
13683 + " FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts "
13684 + " WHERE artifact_tags.artifact_id = arts.artifact_id"
13685 + " AND arts.data_source_obj_id = ?"
13686 + " )"),
13687 INSERT_TAG_NAME("INSERT INTO tag_names (display_name, description, color, knownStatus) VALUES (?, ?, ?, ?)"), //NON-NLS
13688 INSERT_CONTENT_TAG("INSERT INTO content_tags (obj_id, tag_name_id, comment, begin_byte_offset, end_byte_offset, examiner_id) VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
13689 DELETE_CONTENT_TAG("DELETE FROM content_tags WHERE tag_id = ?"), //NON-NLS
13690 COUNT_CONTENT_TAGS_BY_TAG_NAME("SELECT COUNT(*) AS count FROM content_tags WHERE tag_name_id = ?"), //NON-NLS
13692 "SELECT COUNT(*) AS count FROM content_tags as content_tags, tsk_files as tsk_files WHERE content_tags.obj_id = tsk_files.obj_id"
13693 + " AND content_tags.tag_name_id = ? "
13694 + " AND tsk_files.data_source_obj_id = ? "
13695 ),
13696 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 "
13697 + "FROM content_tags "
13698 + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
13699 + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS
13700 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 "
13701 + "FROM content_tags "
13702 + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
13703 + "WHERE tag_name_id = ?"), //NON-NLS
13704 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, tag_names.tag_set_id, tsk_examiners.login_name "
13705 + "FROM content_tags "
13706 + "JOIN tsk_os_accounts acc ON content_tags.obj_id = acc.os_account_obj_id "
13707 + "JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
13708 + "JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
13709 + "WHERE content_tags.tag_name_id = ? "
13710 + "AND acc.os_account_obj_id IN (SELECT os_account_obj_id FROM tsk_os_account_instances WHERE data_source_obj_id = ?) "
13711 + "AND acc.db_status = " + OsAccount.OsAccountDbStatus.ACTIVE.getId()
13712 + " UNION "
13713 + "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, tag_names.tag_set_id, tsk_examiners.login_name "
13714 + "FROM content_tags as content_tags, tsk_files as tsk_files, tag_names as tag_names, tsk_examiners as tsk_examiners "
13715 + "WHERE content_tags.examiner_id = tsk_examiners.examiner_id "
13716 + "AND content_tags.obj_id = tsk_files.obj_id "
13717 + "AND content_tags.tag_name_id = tag_names.tag_name_id "
13718 + "AND content_tags.tag_name_id = ? "
13719 + "AND tsk_files.data_source_obj_id = ? "), //NON-NLS
13720 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 "
13721 + "FROM content_tags "
13722 + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
13723 + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
13724 + "WHERE tag_id = ?"), //NON-NLS
13725 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 "
13726 + "FROM content_tags "
13727 + "INNER JOIN tag_names ON content_tags.tag_name_id = tag_names.tag_name_id "
13728 + "LEFT OUTER JOIN tsk_examiners ON content_tags.examiner_id = tsk_examiners.examiner_id "
13729 + "WHERE content_tags.obj_id = ?"), //NON-NLS
13730 INSERT_ARTIFACT_TAG("INSERT INTO blackboard_artifact_tags (artifact_id, tag_name_id, comment, examiner_id) "
13731 + "VALUES (?, ?, ?, ?)"), //NON-NLS
13732 DELETE_ARTIFACT_TAG("DELETE FROM blackboard_artifact_tags WHERE tag_id = ?"), //NON-NLS
13733 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 "
13734 + "FROM blackboard_artifact_tags "
13735 + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
13736 + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id"), //NON-NLS
13737 COUNT_ARTIFACTS_BY_TAG_NAME("SELECT COUNT(*) AS count FROM blackboard_artifact_tags WHERE tag_name_id = ?"), //NON-NLS
13738 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"
13739 + " AND artifact_tags.tag_name_id = ?"
13740 + " AND arts.data_source_obj_id = ? "),
13741 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 "
13742 + "FROM blackboard_artifact_tags "
13743 + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
13744 + "WHERE tag_name_id = ?"), //NON-NLS
13745 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 "
13746 + "FROM blackboard_artifact_tags as artifact_tags, blackboard_artifacts AS arts, tsk_examiners AS tsk_examiners "
13747 + "WHERE artifact_tags.examiner_id = tsk_examiners.examiner_id"
13748 + " AND artifact_tags.artifact_id = arts.artifact_id"
13749 + " AND artifact_tags.tag_name_id = ? "
13750 + " AND arts.data_source_obj_id = ? "),
13751 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 "
13752 + "FROM blackboard_artifact_tags "
13753 + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
13754 + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
13755 + "WHERE blackboard_artifact_tags.tag_id = ?"), //NON-NLS
13756 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 "
13757 + "FROM blackboard_artifact_tags "
13758 + "INNER JOIN tag_names ON blackboard_artifact_tags.tag_name_id = tag_names.tag_name_id "
13759 + "LEFT OUTER JOIN tsk_examiners ON blackboard_artifact_tags.examiner_id = tsk_examiners.examiner_id "
13760 + "WHERE blackboard_artifact_tags.artifact_id = ?"), //NON-NLS
13761 SELECT_REPORTS("SELECT * FROM reports"), //NON-NLS
13762 SELECT_REPORT_BY_ID("SELECT * FROM reports WHERE obj_id = ?"), //NON-NLS
13763 INSERT_REPORT("INSERT INTO reports (obj_id, path, crtime, src_module_name, report_name) VALUES (?, ?, ?, ?, ?)"), //NON-NLS
13764 DELETE_REPORT("DELETE FROM reports WHERE reports.obj_id = ?"), //NON-NLS
13765 DELETE_REPORT_TSK_OBJECT("DELETE FROM tsk_objects where tsk_objects.obj_id = ? and tsk_objects.type = ?"),
13766 INSERT_INGEST_JOB("INSERT INTO ingest_jobs (obj_id, host_name, start_date_time, end_date_time, status_id, settings_dir) VALUES (?, ?, ?, ?, ?, ?)"), //NON-NLS
13767 INSERT_INGEST_MODULE("INSERT INTO ingest_modules (display_name, unique_name, type_id, version) VALUES(?, ?, ?, ?)"), //NON-NLS
13768 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
13769 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
13770 UPDATE_IMAGE_PATH("UPDATE tsk_image_names SET name = ? WHERE obj_id = ?"), // NON-NLS
13771 SELECT_ARTIFACT_OBJECTIDS_BY_PARENT("SELECT blackboard_artifacts.artifact_obj_id AS artifact_obj_id " //NON-NLS
13772 + "FROM tsk_objects INNER JOIN blackboard_artifacts " //NON-NLS
13773 + "ON tsk_objects.obj_id=blackboard_artifacts.obj_id " //NON-NLS
13774 + "WHERE (tsk_objects.par_obj_id = ?)"),
13775 SELECT_EXAMINER_BY_ID("SELECT * FROM tsk_examiners WHERE examiner_id = ?"),
13776 SELECT_EXAMINER_BY_LOGIN_NAME("SELECT * FROM tsk_examiners WHERE login_name = ?"),
13777 INSERT_EXAMINER_POSTGRESQL("INSERT INTO tsk_examiners (login_name) VALUES (?) ON CONFLICT DO NOTHING"),
13778 INSERT_EXAMINER_SQLITE("INSERT OR IGNORE INTO tsk_examiners (login_name) VALUES (?)"),
13779 UPDATE_FILE_NAME("UPDATE tsk_files SET name = ? WHERE obj_id = ?"),
13780 UPDATE_IMAGE_NAME("UPDATE tsk_image_info SET display_name = ? WHERE obj_id = ?"),
13781 UPDATE_IMAGE_SIZES("UPDATE tsk_image_info SET size = ?, ssize = ? WHERE obj_id = ?"),
13782 DELETE_IMAGE_NAME("DELETE FROM tsk_image_names WHERE obj_id = ?"),
13783 INSERT_IMAGE_NAME("INSERT INTO tsk_image_names (obj_id, name, sequence) VALUES (?, ?, ?)"),
13784 INSERT_IMAGE_INFO("INSERT INTO tsk_image_info (obj_id, type, ssize, tzone, size, md5, sha1, sha256, display_name)"
13785 + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"),
13786 INSERT_DATA_SOURCE_INFO("INSERT INTO data_source_info (obj_id, device_id, time_zone, added_date_time, host_id, acquisition_tool_settings) VALUES (?, ?, ?, ?, ?, ?)"),
13787 INSERT_VS_INFO("INSERT INTO tsk_vs_info (obj_id, vs_type, img_offset, block_size) VALUES (?, ?, ?, ?)"),
13788 INSERT_VS_PART_SQLITE("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, desc, flags) VALUES (?, ?, ?, ?, ?, ?)"),
13789 INSERT_VS_PART_POSTGRESQL("INSERT INTO tsk_vs_parts (obj_id, addr, start, length, descr, flags) VALUES (?, ?, ?, ?, ?, ?)"),
13790 INSERT_POOL_INFO("INSERT INTO tsk_pool_info (obj_id, pool_type) VALUES (?, ?)"),
13791 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)"
13792 + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"),
13793 SELECT_TAG_NAME_BY_ID("SELECT * FROM tag_names where tag_name_id = ?");
13794
13795 private final String sql;
13796
13797 private PREPARED_STATEMENT(String sql) {
13798 this.sql = sql;
13799 }
13800
13801 String getSQL() {
13802 return sql;
13803 }
13804 }
13805
13811 abstract private class ConnectionPool {
13812
13813 private PooledDataSource pooledDataSource;
13814
13815 public ConnectionPool() {
13816 pooledDataSource = null;
13817 }
13818
13819 CaseDbConnection getConnection() throws TskCoreException {
13820 if (pooledDataSource == null) {
13821 throw new TskCoreException("Error getting case database connection - case is closed");
13822 }
13823 try {
13824 return getPooledConnection();
13825 } catch (SQLException exp) {
13826 throw new TskCoreException(exp.getMessage());
13827 }
13828 }
13829
13830 void close() throws TskCoreException {
13831 if (pooledDataSource != null) {
13832 try {
13833 pooledDataSource.close();
13834 } catch (SQLException exp) {
13835 throw new TskCoreException(exp.getMessage());
13836 } finally {
13837 pooledDataSource = null;
13838 }
13839 }
13840 }
13841
13842 abstract CaseDbConnection getPooledConnection() throws SQLException;
13843
13844 public PooledDataSource getPooledDataSource() {
13845 return pooledDataSource;
13846 }
13847
13848 public void setPooledDataSource(PooledDataSource pooledDataSource) {
13849 this.pooledDataSource = pooledDataSource;
13850 }
13851 }
13852
13857 private final class SQLiteConnections extends ConnectionPool {
13858
13859 private final Map<String, String> configurationOverrides = new HashMap<String, String>();
13860
13861 SQLiteConnections(String dbPath, boolean useWAL) throws SQLException {
13862 configurationOverrides.put("acquireIncrement", "2");
13863 configurationOverrides.put("initialPoolSize", "5");
13864 configurationOverrides.put("minPoolSize", "5");
13865 /*
13866 * NOTE: max pool size and max statements are related. If you
13867 * increase max pool size, then also increase statements.
13868 */
13869 configurationOverrides.put("maxPoolSize", "20");
13870 configurationOverrides.put("maxStatements", "200");
13871 configurationOverrides.put("maxStatementsPerConnection", "20");
13872
13873 SQLiteConfig config = new SQLiteConfig();
13874 config.setSynchronous(SQLiteConfig.SynchronousMode.OFF); // Reduce I/O operations, we have no OS crash recovery anyway.
13875 config.setReadUncommitted(true);
13876 config.enforceForeignKeys(true); // Enforce foreign key constraints.
13877 if (useWAL) {
13878 config.setJournalMode(SQLiteConfig.JournalMode.WAL);
13879 }
13880 SQLiteDataSource unpooled = new SQLiteDataSource(config);
13881 unpooled.setUrl("jdbc:sqlite:" + dbPath);
13882 setPooledDataSource((PooledDataSource) DataSources.pooledDataSource(unpooled, configurationOverrides));
13883 }
13884
13885 @Override
13886 public CaseDbConnection getPooledConnection() throws SQLException {
13887 // If the requesting thread already has an open transaction, the new connection may get SQLITE_BUSY errors.
13888 if (CaseDbTransaction.hasOpenTransaction(Thread.currentThread().getId())) {
13889 // Temporarily filter out Image Gallery threads
13890 if (!Thread.currentThread().getName().contains("ImageGallery")) {
13891 logger.log(Level.WARNING, String.format("Thread %s (ID = %d) already has an open transaction. New connection may encounter SQLITE_BUSY error. ", Thread.currentThread().getName(), Thread.currentThread().getId()), new Throwable());
13892 }
13893 }
13894 java.sql.Connection conn = getPooledDataSource().getConnection();
13895 CaseDbConnection caseDbConn = new SQLiteConnection(conn);
13896 return caseDbConn;
13897 }
13898 }
13899
13904 private final class PostgreSQLConnections extends ConnectionPool {
13905
13906 PostgreSQLConnections(CaseDbConnectionInfo info, String dbName) throws PropertyVetoException, UnsupportedEncodingException {
13907
13908 ComboPooledDataSource comboPooledDataSource = new ComboPooledDataSource();
13909 comboPooledDataSource.setDriverClass("org.postgresql.Driver"); //loads the jdbc driver
13910
13911 String connectionURL = "jdbc:postgresql://" + info.getHost() + ":" + Integer.valueOf(info.getPort()) + "/"
13912 + URLEncoder.encode(dbName, StandardCharsets.UTF_8.toString());
13913 if (info.isSslEnabled()) {
13914 if (info.isSslVerify()) {
13915 if (info.getCustomSslValidationClassName().isBlank()) {
13916 connectionURL += CaseDatabaseFactory.SSL_VERIFY_DEFAULT_URL;
13917 } else {
13918 // use custom SSL certificate validation class
13919 connectionURL += CaseDatabaseFactory.getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName());
13920 }
13921 } else {
13922 connectionURL += CaseDatabaseFactory.SSL_NONVERIFY_URL;
13923 }
13924 }
13925 comboPooledDataSource.setJdbcUrl(connectionURL);
13926 comboPooledDataSource.setUser(info.getUserName());
13927 comboPooledDataSource.setPassword(info.getPassword());
13928 comboPooledDataSource.setAcquireIncrement(2);
13929 comboPooledDataSource.setInitialPoolSize(5);
13930 comboPooledDataSource.setMinPoolSize(5);
13931 /*
13932 * NOTE: max pool size and max statements are related. If you
13933 * increase max pool size, then also increase statements.
13934 */
13935 comboPooledDataSource.setMaxPoolSize(20);
13936 comboPooledDataSource.setMaxStatements(200);
13937 comboPooledDataSource.setMaxStatementsPerConnection(20);
13938 setPooledDataSource(comboPooledDataSource);
13939 }
13940
13941 @Override
13942 public CaseDbConnection getPooledConnection() throws SQLException {
13943 return new PostgreSQLConnection(getPooledDataSource().getConnection());
13944 }
13945 }
13946
13950 abstract class CaseDbConnection implements AutoCloseable {
13951
13952 static final int SLEEP_LENGTH_IN_MILLISECONDS = 5000;
13953 static final int MAX_RETRIES = 20; //MAX_RETRIES * SLEEP_LENGTH_IN_MILLESECONDS = max time to hang attempting connection
13954
13955 private class CreateStatement implements DbCommand {
13956
13957 private final Connection connection;
13958 private Statement statement = null;
13959
13960 CreateStatement(Connection connection) {
13961 this.connection = connection;
13962 }
13963
13964 Statement getStatement() {
13965 return statement;
13966 }
13967
13968 @Override
13969 public void execute() throws SQLException {
13970 statement = connection.createStatement();
13971 }
13972 }
13973
13974 private class SetAutoCommit implements DbCommand {
13975
13976 private final Connection connection;
13977 private final boolean mode;
13978
13979 SetAutoCommit(Connection connection, boolean mode) {
13980 this.connection = connection;
13981 this.mode = mode;
13982 }
13983
13984 @Override
13985 public void execute() throws SQLException {
13986 connection.setAutoCommit(mode);
13987 }
13988 }
13989
13990 private class Commit implements DbCommand {
13991
13992 private final Connection connection;
13993
13994 Commit(Connection connection) {
13995 this.connection = connection;
13996 }
13997
13998 @Override
13999 public void execute() throws SQLException {
14000 connection.commit();
14001 }
14002 }
14003
14012 private class AggregateScoreTablePostgreSQLWriteLock implements DbCommand {
14013
14014 private final Connection connection;
14015
14016 AggregateScoreTablePostgreSQLWriteLock(Connection connection) {
14017 this.connection = connection;
14018 }
14019
14020 @Override
14021 public void execute() throws SQLException {
14022 try (PreparedStatement preparedStatement =
14023 connection.prepareStatement("LOCK TABLE ONLY tsk_aggregate_score in SHARE ROW EXCLUSIVE MODE")) {
14024 preparedStatement.execute();
14025 }
14026 }
14027 }
14028
14029 private class ExecuteQuery implements DbCommand {
14030
14031 private final Statement statement;
14032 private final String query;
14033 private ResultSet resultSet;
14034
14035 ExecuteQuery(Statement statement, String query) {
14036 this.statement = statement;
14037 this.query = query;
14038 }
14039
14040 ResultSet getResultSet() {
14041 return resultSet;
14042 }
14043
14044 @Override
14045 public void execute() throws SQLException {
14046 resultSet = statement.executeQuery(query);
14047 }
14048 }
14049
14050 private class ExecutePreparedStatementQuery implements DbCommand {
14051
14052 private final PreparedStatement preparedStatement;
14053 private ResultSet resultSet;
14054
14055 ExecutePreparedStatementQuery(PreparedStatement preparedStatement) {
14056 this.preparedStatement = preparedStatement;
14057 }
14058
14059 ResultSet getResultSet() {
14060 return resultSet;
14061 }
14062
14063 @Override
14064 public void execute() throws SQLException {
14065 resultSet = preparedStatement.executeQuery();
14066 }
14067 }
14068
14069 private class ExecutePreparedStatementUpdate implements DbCommand {
14070
14071 private final PreparedStatement preparedStatement;
14072
14073 ExecutePreparedStatementUpdate(PreparedStatement preparedStatement) {
14074 this.preparedStatement = preparedStatement;
14075 }
14076
14077 @Override
14078 public void execute() throws SQLException {
14079 preparedStatement.executeUpdate();
14080 }
14081 }
14082
14083 private class ExecuteStatementUpdate implements DbCommand {
14084
14085 private final Statement statement;
14086 private final String updateCommand;
14087
14088 ExecuteStatementUpdate(Statement statement, String updateCommand) {
14089 this.statement = statement;
14090 this.updateCommand = updateCommand;
14091 }
14092
14093 @Override
14094 public void execute() throws SQLException {
14095 statement.executeUpdate(updateCommand);
14096 }
14097 }
14098
14099 private class ExecuteStatementUpdateGenerateKeys implements DbCommand {
14100
14101 private final Statement statement;
14102 private final int generateKeys;
14103 private final String updateCommand;
14104
14105 ExecuteStatementUpdateGenerateKeys(Statement statement, String updateCommand, int generateKeys) {
14106 this.statement = statement;
14107 this.generateKeys = generateKeys;
14108 this.updateCommand = updateCommand;
14109 }
14110
14111 @Override
14112 public void execute() throws SQLException {
14113 statement.executeUpdate(updateCommand, generateKeys);
14114 }
14115 }
14116
14117 private class PrepareStatement implements DbCommand {
14118
14119 private final Connection connection;
14120 private final String input;
14121 private PreparedStatement preparedStatement = null;
14122
14123 PrepareStatement(Connection connection, String input) {
14124 this.connection = connection;
14125 this.input = input;
14126 }
14127
14128 PreparedStatement getPreparedStatement() {
14129 return preparedStatement;
14130 }
14131
14132 @Override
14133 public void execute() throws SQLException {
14134 preparedStatement = connection.prepareStatement(input);
14135 }
14136 }
14137
14138 private class PrepareStatementGenerateKeys implements DbCommand {
14139
14140 private final Connection connection;
14141 private final String input;
14142 private final int generateKeys;
14143 private PreparedStatement preparedStatement = null;
14144
14145 PrepareStatementGenerateKeys(Connection connection, String input, int generateKeysInput) {
14146 this.connection = connection;
14147 this.input = input;
14148 this.generateKeys = generateKeysInput;
14149 }
14150
14151 PreparedStatement getPreparedStatement() {
14152 return preparedStatement;
14153 }
14154
14155 @Override
14156 public void execute() throws SQLException {
14157 preparedStatement = connection.prepareStatement(input, generateKeys);
14158 }
14159 }
14160
14161 abstract void executeCommand(DbCommand command) throws SQLException;
14162
14163 private final Connection connection;
14164 private final Map<PREPARED_STATEMENT, PreparedStatement> preparedStatements;
14165 private final Map<String, PreparedStatement> adHocPreparedStatements;
14166
14167 CaseDbConnection(Connection connection) {
14168 this.connection = connection;
14169 preparedStatements = new EnumMap<PREPARED_STATEMENT, PreparedStatement>(PREPARED_STATEMENT.class);
14170 adHocPreparedStatements = new HashMap<>();
14171 }
14172
14173 boolean isOpen() {
14174 return this.connection != null;
14175 }
14176
14177 PreparedStatement getPreparedStatement(PREPARED_STATEMENT statementKey) throws SQLException {
14178 return getPreparedStatement(statementKey, Statement.NO_GENERATED_KEYS);
14179 }
14180
14181 PreparedStatement getPreparedStatement(PREPARED_STATEMENT statementKey, int generateKeys) throws SQLException {
14182 // Lazy statement preparation.
14183 PreparedStatement statement;
14184 if (this.preparedStatements.containsKey(statementKey)) {
14185 statement = this.preparedStatements.get(statementKey);
14186 } else {
14187 statement = prepareStatement(statementKey.getSQL(), generateKeys);
14188 this.preparedStatements.put(statementKey, statement);
14189 }
14190 return statement;
14191 }
14192
14204 PreparedStatement getPreparedStatement(String sqlStatement, int generateKeys) throws SQLException {
14205 PreparedStatement statement;
14206 String statementKey = "SQL:" + sqlStatement + " Key:" + generateKeys;
14207 if (adHocPreparedStatements.containsKey(statementKey) && !adHocPreparedStatements.get(statementKey).isClosed()) {
14208 statement = this.adHocPreparedStatements.get(statementKey);
14209 } else {
14210 statement = prepareStatement(sqlStatement, generateKeys);
14211 this.adHocPreparedStatements.put(statementKey, statement);
14212 }
14213 return statement;
14214 }
14215
14216 PreparedStatement prepareStatement(String sqlStatement, int generateKeys) throws SQLException {
14217 PrepareStatement prepareStatement = new PrepareStatement(this.getConnection(), sqlStatement);
14218 executeCommand(prepareStatement);
14219 return prepareStatement.getPreparedStatement();
14220 }
14221
14222 Statement createStatement() throws SQLException {
14223 CreateStatement createStatement = new CreateStatement(this.connection);
14224 executeCommand(createStatement);
14225 return createStatement.getStatement();
14226 }
14227
14228 void beginTransaction() throws SQLException {
14229 SetAutoCommit setAutoCommit = new SetAutoCommit(connection, false);
14230 executeCommand(setAutoCommit);
14231 }
14232
14233 void commitTransaction() throws SQLException {
14234 Commit commit = new Commit(connection);
14235 executeCommand(commit);
14236 // You must turn auto commit back on when done with the transaction.
14237 SetAutoCommit setAutoCommit = new SetAutoCommit(connection, true);
14238 executeCommand(setAutoCommit);
14239 }
14240
14246 void rollbackTransaction() {
14247 try {
14248 connection.rollback();
14249 } catch (SQLException e) {
14250 logger.log(Level.SEVERE, "Error rolling back transaction", e);
14251 }
14252 try {
14253 connection.setAutoCommit(true);
14254 } catch (SQLException e) {
14255 logger.log(Level.SEVERE, "Error restoring auto-commit", e);
14256 }
14257 }
14258
14266 void rollbackTransactionWithThrow() throws SQLException {
14267 try {
14268 connection.rollback();
14269 } finally {
14270 connection.setAutoCommit(true);
14271 }
14272 }
14273
14282 void getAggregateScoreTableWriteLock() throws SQLException, TskCoreException {
14283 switch (getDatabaseType()) {
14284 case POSTGRESQL:
14285 AggregateScoreTablePostgreSQLWriteLock tableWriteLock = new AggregateScoreTablePostgreSQLWriteLock(connection);
14286 executeCommand(tableWriteLock);
14287 break;
14288 case SQLITE:
14289 // We do nothing here because we assume the entire SQLite DB is already locked from
14290 // when the analysis results were added/deleted in the same transaction.
14291 break;
14292 default:
14293 throw new TskCoreException("Unknown DB Type: " + getDatabaseType().name());
14294 }
14295 }
14296
14297 ResultSet executeQuery(Statement statement, String query) throws SQLException {
14298 ExecuteQuery queryCommand = new ExecuteQuery(statement, query);
14299 executeCommand(queryCommand);
14300 return queryCommand.getResultSet();
14301 }
14302
14312 ResultSet executeQuery(PreparedStatement statement) throws SQLException {
14313 ExecutePreparedStatementQuery executePreparedStatementQuery = new ExecutePreparedStatementQuery(statement);
14314 executeCommand(executePreparedStatementQuery);
14315 return executePreparedStatementQuery.getResultSet();
14316 }
14317
14318 void executeUpdate(Statement statement, String update) throws SQLException {
14319 executeUpdate(statement, update, Statement.NO_GENERATED_KEYS);
14320 }
14321
14322 void executeUpdate(Statement statement, String update, int generateKeys) throws SQLException {
14323 ExecuteStatementUpdate executeStatementUpdate = new ExecuteStatementUpdate(statement, update);
14324 executeCommand(executeStatementUpdate);
14325 }
14326
14327 void executeUpdate(PreparedStatement statement) throws SQLException {
14328 ExecutePreparedStatementUpdate executePreparedStatementUpdate = new ExecutePreparedStatementUpdate(statement);
14329 executeCommand(executePreparedStatementUpdate);
14330 }
14331
14335 @Override
14336 public void close() {
14337 try {
14338 for (PreparedStatement stmt : preparedStatements.values()) {
14339 closeStatement(stmt);
14340 }
14341 for (PreparedStatement stmt : adHocPreparedStatements.values()) {
14342 closeStatement(stmt);
14343 }
14344 connection.close();
14345 } catch (SQLException ex) {
14346 logger.log(Level.SEVERE, "Unable to close connection to case database", ex);
14347 }
14348 }
14349
14350 Connection getConnection() {
14351 return this.connection;
14352 }
14353 }
14354
14358 private final class SQLiteConnection extends CaseDbConnection {
14359
14360 private static final int DATABASE_LOCKED_ERROR = 0; // This should be 6 according to documentation, but it has been observed to be 0.
14361 private static final int SQLITE_BUSY_ERROR = 5;
14362
14363 SQLiteConnection(Connection conn) {
14364 super(conn);
14365 }
14366
14367 @Override
14368 void executeCommand(DbCommand command) throws SQLException {
14369 int retryCounter = 0;
14370 while (true) {
14371 try {
14372 command.execute(); // Perform the operation
14373 break;
14374 } catch (SQLException ex) {
14375 if ((ex.getErrorCode() == SQLITE_BUSY_ERROR || ex.getErrorCode() == DATABASE_LOCKED_ERROR) && retryCounter < MAX_RETRIES) {
14376 try {
14377
14378 // We do not notify of error here, as this is not an
14379 // error condition. It is likely a temporary busy or
14380 // locked issue and we will retry.
14381 retryCounter++;
14382 Thread.sleep(SLEEP_LENGTH_IN_MILLISECONDS);
14383 } catch (InterruptedException exp) {
14384 Logger.getLogger(SleuthkitCase.class.getName()).log(Level.WARNING, "Unexpectedly unable to wait for database.", exp);
14385 }
14386 } else {
14387 throw ex;
14388 }
14389 }
14390 }
14391 }
14392 }
14393
14397 private final class PostgreSQLConnection extends CaseDbConnection {
14398
14399 private final String COMMUNICATION_ERROR = PSQLState.COMMUNICATION_ERROR.getState();
14400 private final String SYSTEM_ERROR = PSQLState.SYSTEM_ERROR.getState();
14401 private final String UNKNOWN_STATE = PSQLState.UNKNOWN_STATE.getState();
14402 private static final int MAX_RETRIES = 3;
14403
14404 PostgreSQLConnection(Connection conn) {
14405 super(conn);
14406 }
14407
14408 @Override
14409 void executeUpdate(Statement statement, String update, int generateKeys) throws SQLException {
14410 CaseDbConnection.ExecuteStatementUpdateGenerateKeys executeStatementUpdateGenerateKeys = new CaseDbConnection.ExecuteStatementUpdateGenerateKeys(statement, update, generateKeys);
14411 executeCommand(executeStatementUpdateGenerateKeys);
14412 }
14413
14414 @Override
14415 PreparedStatement prepareStatement(String sqlStatement, int generateKeys) throws SQLException {
14416 CaseDbConnection.PrepareStatementGenerateKeys prepareStatementGenerateKeys = new CaseDbConnection.PrepareStatementGenerateKeys(this.getConnection(), sqlStatement, generateKeys);
14417 executeCommand(prepareStatementGenerateKeys);
14418 return prepareStatementGenerateKeys.getPreparedStatement();
14419 }
14420
14421 @Override
14422 void executeCommand(DbCommand command) throws SQLException {
14423 SQLException lastException = null;
14424 for (int retries = 0; retries < MAX_RETRIES; retries++) {
14425 try {
14426 command.execute();
14427 lastException = null; // reset since we had a successful execution
14428 break;
14429 } catch (SQLException ex) {
14430 lastException = ex;
14431 String sqlState = ex.getSQLState();
14432 if (sqlState == null || sqlState.equals(COMMUNICATION_ERROR) || sqlState.equals(SYSTEM_ERROR) || sqlState.equals(UNKNOWN_STATE)) {
14433 try {
14434 Thread.sleep(SLEEP_LENGTH_IN_MILLISECONDS);
14435 } catch (InterruptedException exp) {
14436 Logger.getLogger(SleuthkitCase.class.getName()).log(Level.WARNING, "Unexpectedly unable to wait for database.", exp);
14437 }
14438 } else {
14439 throw ex;
14440 }
14441 }
14442 }
14443
14444 // rethrow the exception if we bailed because of too many retries
14445 if (lastException != null) {
14446 throw lastException;
14447 }
14448 }
14449 }
14450
14482 public static final class CaseDbTransaction {
14483
14484 private final CaseDbConnection connection;
14485 private final boolean readOnlyTransaction;
14486 private SleuthkitCase sleuthkitCase;
14487
14488 /* This class can store information about what was
14489 * inserted as part of the transaction so that we can
14490 * fire events after the data has been persisted. */
14491
14492 // Score changes are stored as a map keyed by objId to prevent duplicates.
14493 private Map<Long, ScoreChange> scoreChangeMap = new HashMap<>();
14494 private List<Host> hostsAdded = new ArrayList<>();
14495 private List<TimelineEventAddedEvent> timelineEvents = new ArrayList<>();
14496 private List<OsAccount> accountsChanged = new ArrayList<>();
14497 private List<OsAccount> accountsAdded = new ArrayList<>();
14498 private List<TskEvent.MergedAccountsPair> accountsMerged = new ArrayList<>();
14499
14500 private List<Long> deletedOsAccountObjectIds = new ArrayList<>();
14501 private List<Long> deletedResultObjectIds = new ArrayList<>();
14502
14503
14504 // Keep track of which threads have connections to debug deadlocks
14505 private static Set<Long> threadsWithOpenTransaction = new HashSet<>();
14506 private static final Object threadsWithOpenTransactionLock = new Object();
14507
14518 private CaseDbTransaction(SleuthkitCase sleuthkitCase, boolean readOnlyTransaction) throws TskCoreException {
14519 this.sleuthkitCase = sleuthkitCase;
14520 this.readOnlyTransaction = readOnlyTransaction;
14521
14522 if (readOnlyTransaction) {
14523 sleuthkitCase.acquireSingleUserCaseReadLock();
14524 } else {
14525 sleuthkitCase.acquireSingleUserCaseWriteLock();
14526 }
14527
14528 this.connection = sleuthkitCase.getConnection();
14529 try {
14530 synchronized (threadsWithOpenTransactionLock) {
14531 this.connection.beginTransaction();
14532 threadsWithOpenTransaction.add(Thread.currentThread().getId());
14533 }
14534 } catch (SQLException ex) {
14535 if (readOnlyTransaction) {
14536 sleuthkitCase.releaseSingleUserCaseReadLock();
14537 } else {
14538 sleuthkitCase.releaseSingleUserCaseWriteLock();
14539 }
14540 throw new TskCoreException("Failed to create transaction on case database", ex);
14541 }
14542
14543 }
14544
14552 CaseDbConnection getConnection() {
14553 return this.connection;
14554 }
14555
14561 void registerScoreChange(ScoreChange scoreChange) {
14562 scoreChangeMap.put(scoreChange.getObjectId(), scoreChange);
14563 }
14564
14569 void registerTimelineEvent(TimelineEventAddedEvent timelineEvent) {
14570 if (timelineEvent != null) {
14571 timelineEvents.add(timelineEvent);
14572 }
14573 }
14574
14580 void registerAddedHost(Host host) {
14581 if (host != null) {
14582 this.hostsAdded.add(host);
14583 }
14584 }
14585
14591 void registerChangedOsAccount(OsAccount account) {
14592 if (account != null) {
14593 accountsChanged.add(account);
14594 }
14595 }
14596
14602 void registerDeletedOsAccount(long osAccountObjId) {
14603 deletedOsAccountObjectIds.add(osAccountObjId);
14604 }
14605
14611 void registerAddedOsAccount(OsAccount account) {
14612 if (account != null) {
14613 accountsAdded.add(account);
14614 }
14615 }
14616
14623 void registerMergedOsAccount(long sourceOsAccountObjId, long destinationOsAccountObjId) {
14624 accountsMerged.add(new TskEvent.MergedAccountsPair(sourceOsAccountObjId, destinationOsAccountObjId));
14625 }
14626
14633 void registerDeletedAnalysisResult(long analysisResultObjId) {
14634 this.deletedResultObjectIds.add(analysisResultObjId);
14635 }
14636
14645 private static boolean hasOpenTransaction(long threadId) {
14646 synchronized (threadsWithOpenTransactionLock) {
14647 return threadsWithOpenTransaction.contains(threadId);
14648 }
14649 }
14650
14657 public void commit() throws TskCoreException {
14658 try {
14659 this.connection.commitTransaction();
14660 } catch (SQLException ex) {
14661 throw new TskCoreException("Failed to commit transaction on case database", ex);
14662 } finally {
14663 close();
14664
14665 if (!scoreChangeMap.isEmpty()) {
14666 Map<Long, List<ScoreChange>> changesByDataSource = scoreChangeMap.values().stream()
14667 .collect(Collectors.groupingBy(ScoreChange::getDataSourceObjectId));
14668 for (Map.Entry<Long, List<ScoreChange>> entry : changesByDataSource.entrySet()) {
14669 sleuthkitCase.fireTSKEvent(new TskEvent.AggregateScoresChangedEvent(entry.getKey(), ImmutableSet.copyOf(entry.getValue())));
14670 }
14671 }
14672 if (!timelineEvents.isEmpty()) {
14673 for (TimelineEventAddedEvent evt : timelineEvents) {
14674 sleuthkitCase.fireTSKEvent(evt);
14675 }
14676 }
14677 if (!hostsAdded.isEmpty()) {
14678 sleuthkitCase.fireTSKEvent(new TskEvent.HostsAddedTskEvent(hostsAdded));
14679 }
14680 if (!accountsAdded.isEmpty()) {
14681 sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsAddedTskEvent(accountsAdded));
14682 }
14683 if (!accountsChanged.isEmpty()) {
14684 sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsUpdatedTskEvent(accountsChanged));
14685 }
14686 if (!accountsMerged.isEmpty()) {
14687 sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsMergedTskEvent(accountsMerged));
14688 }
14689 if (!deletedOsAccountObjectIds.isEmpty()) {
14690 sleuthkitCase.fireTSKEvent(new TskEvent.OsAccountsDeletedTskEvent(deletedOsAccountObjectIds));
14691 }
14692 if (!deletedResultObjectIds.isEmpty()) {
14693 sleuthkitCase.fireTSKEvent(new TskEvent.AnalysisResultsDeletedTskEvent(deletedResultObjectIds));
14694 }
14695 }
14696 }
14697
14704 public void rollback() throws TskCoreException {
14705 try {
14706 this.connection.rollbackTransactionWithThrow();
14707 } catch (SQLException ex) {
14708 throw new TskCoreException("Case database transaction rollback failed", ex);
14709 } finally {
14710 close();
14711 }
14712 }
14713
14718 void close() {
14719 this.connection.close();
14720 if (readOnlyTransaction) {
14721 sleuthkitCase.releaseSingleUserCaseReadLock();
14722 } else {
14723 sleuthkitCase.releaseSingleUserCaseWriteLock();
14724 }
14725 synchronized (threadsWithOpenTransactionLock) {
14726 threadsWithOpenTransaction.remove(Thread.currentThread().getId());
14727 }
14728 }
14729 }
14730
14740 public final class CaseDbQuery implements AutoCloseable {
14741
14742 private ResultSet resultSet;
14743 private CaseDbConnection connection;
14744
14745 private CaseDbQuery(String query) throws TskCoreException {
14746 this(query, false);
14747 }
14748
14749 private CaseDbQuery(String query, boolean allowWriteQuery) throws TskCoreException {
14750 if (!allowWriteQuery) {
14751 if (!query.regionMatches(true, 0, "SELECT", 0, "SELECT".length())) {
14752 throw new TskCoreException("Unsupported query: Only SELECT queries are supported.");
14753 }
14754 }
14755
14756 SleuthkitCase.this.acquireSingleUserCaseReadLock();
14757 try {
14758 connection = connections.getConnection();
14759 resultSet = connection.executeQuery(connection.createStatement(), query);
14760 } catch (SQLException ex) {
14761 SleuthkitCase.this.releaseSingleUserCaseReadLock();
14762 throw new TskCoreException("Error executing query: ", ex);
14763 } catch (TskCoreException ex) {
14764 SleuthkitCase.this.releaseSingleUserCaseReadLock();
14765 throw ex;
14766 }
14767 }
14768
14774 public ResultSet getResultSet() {
14775 return resultSet;
14776 }
14777
14778 @Override
14779 public void close() throws TskCoreException {
14780 try {
14781 if (resultSet != null) {
14782 final Statement statement = resultSet.getStatement();
14783 if (statement != null) {
14784 statement.close();
14785 }
14786 resultSet.close();
14787 }
14788 closeConnection(connection);
14789 } catch (SQLException ex) {
14790 throw new TskCoreException("Error closing query: ", ex);
14791 } finally {
14792 SleuthkitCase.this.releaseSingleUserCaseReadLock();
14793 }
14794 }
14795 }
14796
14804 @Deprecated
14805 public void addErrorObserver(ErrorObserver observer) {
14806 sleuthkitCaseErrorObservers.add(observer);
14807 }
14808
14816 @Deprecated
14817 public void removeErrorObserver(ErrorObserver observer) {
14818 int i = sleuthkitCaseErrorObservers.indexOf(observer);
14819 if (i >= 0) {
14820 sleuthkitCaseErrorObservers.remove(i);
14821 }
14822 }
14823
14832 @Deprecated
14833 public void submitError(String context, String errorMessage) {
14834 for (ErrorObserver observer : sleuthkitCaseErrorObservers) {
14835 if (observer != null) {
14836 try {
14837 observer.receiveError(context, errorMessage);
14838 } catch (Exception ex) {
14839 logger.log(Level.SEVERE, "Observer client unable to receive message: {0}, {1}", new Object[]{context, errorMessage, ex});
14840
14841 }
14842 }
14843 }
14844 }
14845
14851 @Deprecated
14852 public interface ErrorObserver {
14853
14860 public enum Context {
14861
14865 IMAGE_READ_ERROR("Image File Read Error"),
14869 DATABASE_READ_ERROR("Database Read Error");
14870
14871 private final String contextString;
14872
14873 private Context(String context) {
14874 this.contextString = context;
14875 }
14876
14877 public String getContextString() {
14878 return contextString;
14879 }
14880 };
14881
14882 void receiveError(String context, String errorMessage);
14883 }
14884
14895 @Deprecated
14896 long getDataSourceObjectId(long objectId) {
14897 try {
14898 CaseDbConnection connection = connections.getConnection();
14899 try {
14900 return getDataSourceObjectId(connection, objectId);
14901 } finally {
14902 closeConnection(connection);
14903 }
14904 } catch (TskCoreException ex) {
14905 logger.log(Level.SEVERE, "Error getting data source object id for a file", ex);
14906 return 0;
14907 }
14908 }
14909
14919 @Deprecated
14920 public long getLastObjectId() throws TskCoreException {
14921 CaseDbConnection connection = null;
14922 ResultSet rs = null;
14924 try {
14925 connection = connections.getConnection();
14926
14927 // SELECT MAX(obj_id) AS max_obj_id FROM tsk_objects
14928 PreparedStatement statement = connection.getPreparedStatement(PREPARED_STATEMENT.SELECT_MAX_OBJECT_ID);
14929 rs = connection.executeQuery(statement);
14930 long id = -1;
14931 if (rs.next()) {
14932 id = rs.getLong("max_obj_id");
14933 }
14934 return id;
14935 } catch (SQLException e) {
14936 throw new TskCoreException("Error getting last object id", e);
14937 } finally {
14938 closeResultSet(rs);
14939 closeConnection(connection);
14941 }
14942 }
14943
14957 @Deprecated
14958 public List<FsContent> findFilesWhere(String sqlWhereClause) throws TskCoreException {
14959 CaseDbConnection connection = null;
14960 Statement s = null;
14961 ResultSet rs = null;
14963 try {
14964 connection = connections.getConnection();
14965 s = connection.createStatement();
14966 rs = connection.executeQuery(s, "SELECT * FROM tsk_files WHERE " + sqlWhereClause); //NON-NLS
14967 List<FsContent> results = new ArrayList<FsContent>();
14968 List<AbstractFile> temp = resultSetToAbstractFiles(rs, connection);
14969 for (AbstractFile f : temp) {
14970 final TSK_DB_FILES_TYPE_ENUM type = f.getType();
14971 if (type.equals(TskData.TSK_DB_FILES_TYPE_ENUM.FS)) {
14972 results.add((FsContent) f);
14973 }
14974 }
14975 return results;
14976 } catch (SQLException e) {
14977 throw new TskCoreException("SQLException thrown when calling 'SleuthkitCase.findFilesWhere().", e);
14978 } finally {
14979 closeResultSet(rs);
14980 closeStatement(s);
14981 closeConnection(connection);
14983 }
14984 }
14985
14997 @Deprecated
14998 public int getArtifactTypeID(String artifactTypeName) throws TskCoreException {
15000 try (CaseDbConnection connection = connections.getConnection();
15001 PreparedStatement getTypeNamePrepState = connection.prepareStatement(
15002 "SELECT artifact_type_id FROM blackboard_artifact_types WHERE type_name = ?",
15003 Statement.RETURN_GENERATED_KEYS)) {
15004
15005 getTypeNamePrepState.setString(1, artifactTypeName);
15006
15007 try (ResultSet rs = getTypeNamePrepState.executeQuery()) {
15008 int typeId = -1;
15009 if (rs.next()) {
15010 typeId = rs.getInt("artifact_type_id");
15011 }
15012 return typeId;
15013 }
15014 } catch (SQLException ex) {
15015 throw new TskCoreException("Error getting artifact type id", ex);
15016 } finally {
15018 }
15019 }
15020
15030 @Deprecated
15032 return new ArrayList<BlackboardArtifact.ARTIFACT_TYPE>(Arrays.asList(BlackboardArtifact.ARTIFACT_TYPE.values()));
15033 }
15034
15048 @Deprecated
15049 public int addArtifactType(String artifactTypeName, String displayName) throws TskCoreException {
15050 try {
15051 return addBlackboardArtifactType(artifactTypeName, displayName).getTypeID();
15052 } catch (TskDataException ex) {
15053 throw new TskCoreException("Failed to add artifact type.", ex);
15054 }
15055 }
15056
15070 @Deprecated
15071 public int addAttrType(String attrTypeString, String displayName) throws TskCoreException {
15072 try {
15073 return addArtifactAttributeType(attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE.STRING, displayName).getTypeID();
15074 } catch (TskDataException ex) {
15075 throw new TskCoreException("Couldn't add new attribute type");
15076 }
15077 }
15078
15089 @Deprecated
15090 public int getAttrTypeID(String attrTypeName) throws TskCoreException {
15091 CaseDbConnection connection = null;
15092 Statement s = null;
15093 ResultSet rs = null;
15095 try {
15096 connection = connections.getConnection();
15097 s = connection.createStatement();
15098 rs = connection.executeQuery(s, "SELECT attribute_type_id FROM blackboard_attribute_types WHERE type_name = '" + attrTypeName + "'"); //NON-NLS
15099 int typeId = -1;
15100 if (rs.next()) {
15101 typeId = rs.getInt("attribute_type_id");
15102 }
15103 return typeId;
15104 } catch (SQLException ex) {
15105 throw new TskCoreException("Error getting attribute type id", ex);
15106 } finally {
15107 closeResultSet(rs);
15108 closeStatement(s);
15109 closeConnection(connection);
15111 }
15112 }
15113
15126 @Deprecated
15127 public String getAttrTypeString(int attrTypeID) throws TskCoreException {
15128 CaseDbConnection connection = null;
15129 Statement s = null;
15130 ResultSet rs = null;
15132 try {
15133 connection = connections.getConnection();
15134 s = connection.createStatement();
15135 rs = connection.executeQuery(s, "SELECT type_name FROM blackboard_attribute_types WHERE attribute_type_id = " + attrTypeID); //NON-NLS
15136 if (rs.next()) {
15137 return rs.getString("type_name");
15138 } else {
15139 throw new TskCoreException("No type with that id");
15140 }
15141 } catch (SQLException ex) {
15142 throw new TskCoreException("Error getting or creating a attribute type name", ex);
15143 } finally {
15144 closeResultSet(rs);
15145 closeStatement(s);
15146 closeConnection(connection);
15148 }
15149 }
15150
15163 @Deprecated
15164 public String getAttrTypeDisplayName(int attrTypeID) throws TskCoreException {
15165 CaseDbConnection connection = null;
15166 Statement s = null;
15167 ResultSet rs = null;
15169 try {
15170 connection = connections.getConnection();
15171 s = connection.createStatement();
15172 rs = connection.executeQuery(s, "SELECT display_name FROM blackboard_attribute_types WHERE attribute_type_id = " + attrTypeID); //NON-NLS
15173 if (rs.next()) {
15174 return rs.getString("display_name");
15175 } else {
15176 throw new TskCoreException("No type with that id");
15177 }
15178 } catch (SQLException ex) {
15179 throw new TskCoreException("Error getting or creating a attribute type name", ex);
15180 } finally {
15181 closeResultSet(rs);
15182 closeStatement(s);
15183 closeConnection(connection);
15185 }
15186 }
15187
15197 @Deprecated
15199 return new ArrayList<BlackboardAttribute.ATTRIBUTE_TYPE>(Arrays.asList(BlackboardAttribute.ATTRIBUTE_TYPE.values()));
15200 }
15201
15217 @Deprecated
15218 public ResultSet runQuery(String query) throws SQLException {
15219 CaseDbConnection connection = null;
15221 try {
15222 connection = connections.getConnection();
15223 return connection.executeQuery(connection.createStatement(), query);
15224 } catch (TskCoreException ex) {
15225 throw new SQLException("Error getting connection for ad hoc query", ex);
15226 } finally {
15227 //TODO unlock should be done in closeRunQuery()
15228 //but currently not all code calls closeRunQuery - need to fix this
15229 closeConnection(connection);
15231 }
15232 }
15233
15243 @Deprecated
15244 public void closeRunQuery(ResultSet resultSet) throws SQLException {
15245 final Statement statement = resultSet.getStatement();
15246 resultSet.close();
15247 if (statement != null) {
15248 statement.close();
15249 }
15250 }
15251
15268 @Deprecated
15269 public LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, long containerId, List<TskFileRange> data) throws TskCoreException {
15270 CarvingResult.CarvedFile carvedFile = new CarvingResult.CarvedFile(carvedFileName, carvedFileSize, data);
15271 List<CarvingResult.CarvedFile> files = new ArrayList<CarvingResult.CarvedFile>();
15272 files.add(carvedFile);
15273 CarvingResult carvingResult;
15274 Content parent = getContentById(containerId);
15275 if (parent instanceof FileSystem
15276 || parent instanceof Volume
15277 || parent instanceof Image) {
15278 carvingResult = new CarvingResult(parent, files);
15279 } else {
15280 throw new TskCoreException(String.format("Parent (id =%d) is not an file system, volume or image", containerId));
15281 }
15282 return addCarvedFiles(carvingResult).get(0);
15283 }
15284
15298 @Deprecated
15299 public List<LayoutFile> addCarvedFiles(List<CarvedFileContainer> filesToAdd) throws TskCoreException {
15300 List<CarvingResult.CarvedFile> carvedFiles = new ArrayList<CarvingResult.CarvedFile>();
15301 for (CarvedFileContainer container : filesToAdd) {
15302 CarvingResult.CarvedFile carvedFile = new CarvingResult.CarvedFile(container.getName(), container.getSize(), container.getRanges());
15303 carvedFiles.add(carvedFile);
15304 }
15305 CarvingResult carvingResult;
15306 Content parent = getContentById(filesToAdd.get(0).getId());
15307 if (parent instanceof FileSystem
15308 || parent instanceof Volume
15309 || parent instanceof Image) {
15310 carvingResult = new CarvingResult(parent, carvedFiles);
15311 } else {
15312 throw new TskCoreException(String.format("Parent (id =%d) is not an file system, volume or image", parent.getId()));
15313 }
15314 return addCarvedFiles(carvingResult);
15315 }
15316
15346 @Deprecated
15347 public DerivedFile addDerivedFile(String fileName, String localPath,
15348 long size, long ctime, long crtime, long atime, long mtime,
15349 boolean isFile, AbstractFile parentFile,
15350 String rederiveDetails, String toolName, String toolVersion, String otherDetails) throws TskCoreException {
15351 return addDerivedFile(fileName, localPath, size, ctime, crtime, atime, mtime,
15352 isFile, parentFile, rederiveDetails, toolName, toolVersion,
15353 otherDetails, TskData.EncodingType.NONE);
15354 }
15355
15385 @Deprecated
15386 public LocalFile addLocalFile(String fileName, String localPath,
15387 long size, long ctime, long crtime, long atime, long mtime,
15388 String md5, FileKnown known, String mimeType,
15389 boolean isFile, TskData.EncodingType encodingType,
15390 Content parent, CaseDbTransaction transaction) throws TskCoreException {
15391
15392 return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime,
15393 md5, null, known, mimeType, isFile, encodingType,
15394 parent, transaction);
15395 }
15396
15421 @Deprecated
15422 public LocalFile addLocalFile(String fileName, String localPath,
15423 long size, long ctime, long crtime, long atime, long mtime,
15424 boolean isFile,
15425 AbstractFile parent, CaseDbTransaction transaction) throws TskCoreException {
15426 return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime, isFile,
15427 TskData.EncodingType.NONE, parent, transaction);
15428 }
15429
15449 @Deprecated
15450 public LocalFile addLocalFile(String fileName, String localPath,
15451 long size, long ctime, long crtime, long atime, long mtime,
15452 boolean isFile,
15453 AbstractFile parent) throws TskCoreException {
15454 return addLocalFile(fileName, localPath, size, ctime, crtime, atime, mtime,
15455 isFile, TskData.EncodingType.NONE, parent);
15456 }
15457
15474 @Deprecated
15475 public AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans) {
15476 return this.caseHandle.initAddImageProcess(timezone, addUnallocSpace, noFatFsOrphans, "", null, this);
15477 }
15478
15489 @Deprecated
15490 public Collection<FileSystem> getFileSystems(Image image) {
15491 try {
15492 return getImageFileSystems(image);
15493 } catch (TskCoreException ex) {
15494 logger.log(Level.SEVERE, "Error loading all file systems for image with ID {0}", image.getId());
15495 return new ArrayList<>();
15496 }
15497 }
15498
15516 @Deprecated
15517 public List<AbstractFile> findFiles(Content dataSource, String fileName, AbstractFile parentFile) throws TskCoreException {
15518 return findFilesInFolder(fileName, parentFile);
15519 }
15520
15528 @Deprecated
15529 public void acquireExclusiveLock() {
15531 }
15532
15540 @Deprecated
15541 public void releaseExclusiveLock() {
15543 }
15544
15552 @Deprecated
15553 public void acquireSharedLock() {
15555 }
15556
15564 @Deprecated
15565 public void releaseSharedLock() {
15567 }
15568};
TskData.TSK_DB_FILES_TYPE_ENUM getType()
static String createNonUniquePath(String uniquePath)
BlackboardArtifact.Type getArtifactType(String artTypeName)
BlackboardArtifact.Type getOrAddArtifactType(String typeName, String displayName)
Host getHostByDataSource(DataSource dataSource)
OsAccount getOsAccountByObjectId(long osAccountObjId)
static final Score SCORE_UNKNOWN
Definition Score.java:213
final List< LayoutFile > addCarvedFiles(CarvingResult carvingResult)
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, String md5Hash, String sha256Hash, String sha1Hash, String mimeType, boolean isFile, Content parent, String ownerUid, OsAccount osAccount, List< Attribute > fileAttributes, CaseDbTransaction transaction)
static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath, ContentStreamProvider contentProvider)
List< TskFileRange > getFileRanges(long id)
void updateImagePath(String newPath, long objectId)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(ARTIFACT_TYPE artifactType)
static SleuthkitCase newCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName)
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, Long osAccountId, String ownerAccount, Content parent, CaseDbTransaction transaction)
static SleuthkitCase newCase(String dbPath)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, AbstractFile parent, CaseDbTransaction transaction)
ArrayList< BlackboardAttribute.ATTRIBUTE_TYPE > getBlackboardAttributeTypes()
List< AbstractFile > findFilesByMd5(String md5Hash)
CaseDbAccessManager getCaseDbAccessManager()
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)
Volume addVolume(long parentObjId, long addr, long start, long length, String desc, long flags, CaseDbTransaction transaction)
long getBlackboardArtifactsCount(int artifactTypeID, long obj_id)
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)
static SleuthkitCase newCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName, boolean useWAL)
List< BlackboardArtifact.Type > getArtifactTypesInUse()
long getBlackboardArtifactsCount(String artifactTypeName, long obj_id)
Report addReport(String localPath, String sourceModuleName, String reportName)
List< AbstractFile > findFiles(Content dataSource, String fileName)
LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, CaseDbTransaction transaction)
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, String md5, String sha256, String sha1Hash, FileKnown known, String mimeType, boolean isFile, TskData.EncodingType encodingType, Long osAccountId, String ownerAccount, Content parent, CaseDbTransaction transaction)
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, String md5Hash, String sha256Hash, String mimeType, boolean isFile, Content parent, String ownerUid, OsAccount osAccount, List< Attribute > fileAttributes, CaseDbTransaction transaction)
TagName addTagName(String displayName, String description, TagName.HTML_COLOR color)
static SleuthkitCase newCase(String caseName, CaseDbConnectionInfo info, String caseDirPath)
void setFileMIMEType(AbstractFile file, String mimeType)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(String artifactTypeName, long obj_id)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(ARTIFACT_TYPE artifactType, long obj_id)
long getContentTagsCountByTagName(TagName tagName, long dsObjId)
boolean setKnown(AbstractFile file, FileKnown fileKnown)
List< BlackboardArtifact > getBlackboardArtifacts(ARTIFACT_TYPE artifactType, BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value)
BlackboardArtifact.Type addBlackboardArtifactType(String artifactTypeName, String displayName)
void updateFile(long fileObjId, long size, long mtime, long atime, long ctime, long crtime, String userSid, Long osAcctObjId)
List< ContentTag > getContentTagsByTagName(TagName tagName, long dsObjId)
List< AbstractFile > findFiles(Content dataSource, String fileName, AbstractFile parentFile)
int addAttrType(String attrTypeString, String displayName)
ArrayList< BlackboardAttribute > getBlackboardAttributes(final BlackboardArtifact artifact)
List< ContentTag > getContentTagsByContent(Content content)
ArrayList< BlackboardArtifact.ARTIFACT_TYPE > getBlackboardArtifactTypes()
Image addImageInfo(long deviceObjId, List< String > imageFilePaths, String timeZone)
List< Long > findAllFileIdsWhere(String sqlWhereClause)
TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus)
List< AbstractFile > findFilesInFolder(String fileName, AbstractFile parentFile)
static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, byte value)
VirtualDirectory addVirtualDirectory(long parentId, String directoryName)
List< AbstractFile > findAllFilesWhere(String sqlWhereClause)
BlackboardArtifactTag addBlackboardArtifactTag(BlackboardArtifact artifact, TagName tagName, String comment)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, int value)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(String artifactTypeName)
List< BlackboardAttribute.Type > getAttributeTypes()
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, AbstractFile parent)
ContentTag getContentTagByID(long contentTagID)
List< AbstractFile > findAllFilesInFolderWhere(long parentId, String sqlWhereClause)
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, Host host, CaseDbTransaction transaction)
void setImagePaths(long objId, List< String > paths, CaseDbTransaction trans)
void deleteBlackboardArtifactTag(BlackboardArtifactTag tag)
BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id)
int addArtifactType(String artifactTypeName, String displayName)
int countFsContentType(TskData.TSK_FS_META_TYPE_ENUM contentType)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(int artifactTypeID, long obj_id)
static SleuthkitCase newCase(String dbPath, ContentStreamProvider contentProvider)
final IngestJobInfo addIngestJob(Content dataSource, String hostName, List< IngestModuleInfo > ingestModules, Date jobStart, Date jobEnd, IngestJobStatusType status, String settingsDir)
void addBlackboardAttribute(BlackboardAttribute attr, int artifactTypeId)
void addErrorObserver(ErrorObserver observer)
boolean isFileFromSource(Content dataSource, long fileId)
BlackboardAttribute.Type getAttributeType(String attrTypeName)
void closeRunQuery(ResultSet resultSet)
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, Host host, String password, CaseDbTransaction transaction)
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)
Image addImageInfo(long deviceObjId, List< String > imageFilePaths, String timeZone, Host host)
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, String md5Hash, String sha256Hash, String sha1Hash, String mimeType, boolean isFile, Content parent, String ownerUid, OsAccount osAccount, TskData.CollectedStatus collected, List< Attribute > fileAttributes, CaseDbTransaction transaction)
BlackboardAttribute.Type addArtifactAttributeType(String attrTypeString, TSK_BLACKBOARD_ATTRIBUTE_VALUE_TYPE valueType, String displayName)
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)
BlackboardArtifactTag getBlackboardArtifactTagByID(long artifactTagID)
void addBlackboardAttributes(Collection< BlackboardAttribute > attributes, int artifactTypeId)
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)
Pool addPool(long parentObjId, TskData.TSK_POOL_TYPE_ENUM type, CaseDbTransaction transaction)
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)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByTagName(TagName tagName)
List< FsContent > findFilesWhere(String sqlWhereClause)
List< VirtualDirectory > getVirtualDirectoryRoots()
CommunicationsManager getCommunicationsManager()
static void tryConnect(CaseDbConnectionInfo info)
Image addImageInfo(long deviceObjId, List< String > imageFilePaths, String timeZone, Host host, String password)
final List< IngestJobInfo > getIngestJobs()
static SleuthkitCase openCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName, boolean useWAL)
List< BlackboardArtifactTag > getAllBlackboardArtifactTags()
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String subString, boolean startsWith)
AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath)
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)
VirtualDirectory addVirtualDirectory(long parentId, String directoryName, CaseDbTransaction transaction)
DataSource getDataSource(long objectId)
static SleuthkitCase openCase(String dbPath, ContentStreamProvider contentProvider, String lockingApplicationName)
List< LayoutFile > addCarvedFiles(List< CarvedFileContainer > filesToAdd)
List< AbstractFile > openFiles(Content dataSource, String filePath)
ArrayList< BlackboardAttribute > getMatchingAttributes(String whereClause)
BlackboardArtifact getArtifactById(long id)
static SleuthkitCase openCase(String dbPath)
VolumeSystem addVolumeSystem(long parentObjId, TskData.TSK_VS_TYPE_ENUM type, long imgOffset, long blockSize, CaseDbTransaction transaction)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, String value)
long getBlackboardArtifactTagsCountByTagName(TagName tagName)
LocalDirectory addLocalDirectory(long parentId, String directoryName, CaseDbTransaction transaction)
long getBlackboardArtifactsCount(ARTIFACT_TYPE artifactType, long obj_id)
void setImagePaths(long obj_id, List< String > paths)
long getBlackboardArtifactsTypeCount(int artifactTypeID)
final IngestModuleInfo addIngestModule(String displayName, String factoryClassName, IngestModuleType type, String version)
void removeErrorObserver(ErrorObserver observer)
static SleuthkitCase openCase(String dbPath, ContentStreamProvider contentProvider)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, double value)
Collection< FileSystem > getFileSystems(Image image)
AddImageProcess makeAddImageProcess(String timezone, boolean addUnallocSpace, boolean noFatFsOrphans)
long getBlackboardArtifactTagsCountByTagName(TagName tagName, long dsObjId)
long getContentTagsCountByTagName(TagName tagName)
static SleuthkitCase openCase(String databaseName, CaseDbConnectionInfo info, String caseDir, ContentStreamProvider contentProvider)
List< AbstractFile > findFiles(Content dataSource, String fileName, String dirSubString)
BlackboardArtifact.Type getArtifactType(String artTypeName)
Map< Long, List< String > > getImagePaths()
LocalFile addLocalFile(String fileName, String localPath, long size, long ctime, long crtime, long atime, long mtime, boolean isFile, TskData.EncodingType encodingType, AbstractFile parent)
LayoutFile addCarvedFile(String carvedFileName, long carvedFileSize, long containerId, List< TskFileRange > data)
List< TagName > getTagNamesInUse(long dsObjId)
long getBlackboardArtifactsTypeCount(int artifactTypeID, long dataSourceID)
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)
ArrayList< BlackboardArtifact > getMatchingArtifacts(String whereClause)
CaseDbQuery executeInsertOrUpdate(String query)
LocalFilesDataSource addLocalFilesDataSource(String deviceId, String rootDirectoryName, String timeZone, Host host, CaseDbTransaction transaction)
ContentTag addContentTag(Content content, TagName tagName, String comment, long beginByteOffset, long endByteOffset)
List< BlackboardArtifact > getBlackboardArtifacts(BlackboardAttribute.ATTRIBUTE_TYPE attrType, long value)
ArrayList< BlackboardArtifact > getBlackboardArtifacts(int artifactTypeID)
List< ContentTag > getContentTagsByTagName(TagName tagName)
CaseDbSchemaVersionNumber getDBSchemaCreationVersion()
BlackboardArtifact getArtifactByArtifactId(long id)
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, CaseDbTransaction transaction)
String getAttrTypeDisplayName(int attrTypeID)
long countFilesWhere(String sqlWhereClause)
void setReviewStatus(BlackboardArtifact artifact, BlackboardArtifact.ReviewStatus newStatus)
Iterable< BlackboardArtifact.Type > getArtifactTypes()
Report addReport(String localPath, String sourceModuleName, String reportName, Content parent)
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)
AddImageProcess makeAddImageProcess(String timeZone, boolean addUnallocSpace, boolean noFatFsOrphans, String imageCopyPath, String password)
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, Content parentObj, CaseDbTransaction trans)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByTagName(TagName tagName, long dsObjId)
int getArtifactTypeID(String artifactTypeName)
Collection< FileSystem > getImageFileSystems(Image image)
final List< LayoutFile > addLayoutFiles(Content parent, List< TskFileRange > fileRanges)
BlackboardArtifact getBlackboardArtifact(long artifactID)
static String escapeSingleQuotes(String text)
ArrayList< BlackboardArtifact.ARTIFACT_TYPE > getBlackboardArtifactTypesInUse()
OsAccountRealmManager getOsAccountRealmManager()
LocalDirectory addLocalDirectory(long parentId, String directoryName)
List< BlackboardArtifactTag > getBlackboardArtifactTagsByArtifact(BlackboardArtifact artifact)
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)
void submitError(String context, String errorMessage)
TagName addOrUpdateTagName(String displayName, String description, TagName.HTML_COLOR color, TskData.FileKnown knownStatus)
static Priority fromID(int id)
Definition Score.java:184
static Significance fromID(int id)
Definition Score.java:118
static HTML_COLOR getColorByName(String colorName)
Definition TagName.java:76
UNKNOWN
File marked as unknown by hash db.
Definition TskData.java:802
static ObjectType valueOf(short objectType)
Definition TskData.java:679
REPORT
Artifact - see blackboard_artifacts for more details.
Definition TskData.java:644
VOL
Volume - see tsk_vs_parts for more details.
Definition TskData.java:640
IMG
Disk Image - see tsk_image_info for more details.
Definition TskData.java:638
VS
Volume System - see tsk_vs_info for more details.
Definition TskData.java:639
FS
File System - see tsk_fs_info for more details.
Definition TskData.java:641
ABSTRACTFILE
File - see tsk_files for more details.
Definition TskData.java:642
LAYOUT_FILE
Set of blocks from an image that have been designated as a file.
Definition TskData.java:704
FS
File that can be found in file system tree.
Definition TskData.java:695
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:696
LOCAL_DIR
Local directory that was added (not from a disk image).
Definition TskData.java:703
LOCAL
Local file that was added (not from a disk image).
Definition TskData.java:698
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:701
DERIVED
File derived from a parent file (i.e. from ZIP).
Definition TskData.java:697
UNALLOC_BLOCKS
Set of blocks not allocated by file system. Parent should be image, volume, or file system....
Definition TskData.java:699
static short toInt(Set< TSK_FS_META_FLAG_ENUM > metaFlags)
Definition TskData.java:268
UNALLOC
Metadata structure is currently in an unallocated state.
Definition TskData.java:209
static Set< TSK_FS_META_FLAG_ENUM > valuesOf(short metaFlags)
Definition TskData.java:249
ALLOC
Metadata structure is currently in an allocated state.
Definition TskData.java:208
USED
Metadata structure has been allocated at least once.
Definition TskData.java:210
static TSK_FS_TYPE_ENUM valueOf(int fsTypeValue)
Definition TskData.java:509
static TagType valueOf(byte type)
Definition TskData.java:922
DataArtifact newDataArtifact(BlackboardArtifact.Type artifactType, Collection< BlackboardAttribute > attributesList)
AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type artifactType, Score score, String conclusion, String configuration, String justification, Collection< BlackboardAttribute > attributesList)
List< Content > getChildren()
void receiveError(String context, String errorMessage)

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