Sleuth Kit Java Bindings (JNI)  4.5.0
Java bindings for using The Sleuth Kit
CommunicationsManager.java
Go to the documentation of this file.
1 /*
2  * Sleuth Kit Data Model
3  *
4  * Copyright 2017 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.datamodel;
20 
21 import java.sql.ResultSet;
22 import java.sql.SQLException;
23 import java.sql.Statement;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.Iterator;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.logging.Level;
36 import java.util.logging.Logger;
38 import static org.sleuthkit.datamodel.SleuthkitCase.closeResultSet;
39 import static org.sleuthkit.datamodel.SleuthkitCase.closeStatement;
40 
45 public class CommunicationsManager {
46 
47  private static final Logger LOGGER = Logger.getLogger(CommunicationsManager.class.getName());
48 
49  private final SleuthkitCase db;
50 
51  private final Map<Account.Type, Integer> accountTypeToTypeIdMap
52  = new ConcurrentHashMap<Account.Type, Integer>();
53  private final Map<String, Account.Type> typeNameToAccountTypeMap
54  = new ConcurrentHashMap<String, Account.Type>();
55 
56  // Artifact types that represent a relationship between accounts
57  private final static Set<Integer> RELATIONSHIP_ARTIFACT_TYPE_IDS
58  = new HashSet<Integer>(Arrays.asList(
63  ));
64  private static final String RELATIONSHIP_ARTIFACT_TYPE_IDS_CSV_STR
65  = StringUtils.buildCSVString(RELATIONSHIP_ARTIFACT_TYPE_IDS);
66 
68  this.db = db;
69 
71  }
72 
78  private void initAccountTypes() throws TskCoreException {
79  CaseDbConnection connection = db.getConnection();
81  Statement statement = null;
82  ResultSet resultSet = null;
83 
84  try {
85  statement = connection.createStatement();
86  // Read the table
87  int count = readAccountTypes();
88  if (0 == count) {
89  // Table is empty, populate it with predefined types
91  try {
92  statement.execute("INSERT INTO account_types (type_name, display_name) VALUES ( '" + type.getTypeName() + "', '" + type.getDisplayName() + "')"); //NON-NLS
93  } catch (SQLException ex) {
94  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM account_types WHERE type_name = '" + type.getTypeName() + "'"); //NON-NLS
95  resultSet.next();
96  if (resultSet.getLong("count") == 0) {
97  throw ex;
98  }
99  resultSet.close();
100  resultSet = null;
101  }
102 
103  ResultSet rs2 = connection.executeQuery(statement, "SELECT account_type_id FROM account_types WHERE type_name = '" + type.getTypeName() + "'"); //NON-NLS
104  rs2.next();
105  int typeID = rs2.getInt("account_type_id");
106  rs2.close();
107 
108  Account.Type accountType = new Account.Type(type.getTypeName(), type.getDisplayName());
109  this.accountTypeToTypeIdMap.put(accountType, typeID);
110  this.typeNameToAccountTypeMap.put(type.getTypeName(), accountType);
111  }
112  }
113  } catch (SQLException ex) {
114  LOGGER.log(Level.SEVERE, "Failed to add row to account_types", ex);
115  } finally {
116  closeResultSet(resultSet);
117  closeStatement(statement);
118  connection.close();
120  }
121  }
122 
133  private int readAccountTypes() throws SQLException, TskCoreException {
134  CaseDbConnection connection = db.getConnection();
136  Statement statement = null;
137  ResultSet resultSet = null;
138  int count = 0;
139 
140  try {
141  statement = connection.createStatement();
142 
143  // If the account_types table is already populated, say when opening a case, then load it
144  resultSet = connection.executeQuery(statement, "SELECT COUNT(*) AS count FROM account_types"); //NON-NLS
145  resultSet.next();
146  if (resultSet.getLong("count") > 0) {
147 
148  resultSet.close();
149  resultSet = connection.executeQuery(statement, "SELECT * FROM account_types");
150  while (resultSet.next()) {
151  Account.Type accountType = new Account.Type(resultSet.getString("type_name"), resultSet.getString("display_name"));
152  this.accountTypeToTypeIdMap.put(accountType, resultSet.getInt("account_type_id"));
153  this.typeNameToAccountTypeMap.put(accountType.getTypeName(), accountType);
154  }
155  count = this.typeNameToAccountTypeMap.size();
156  }
157 
158  } catch (SQLException ex) {
159  LOGGER.log(Level.SEVERE, "Failed to read account_types", ex);
160  } finally {
161  closeResultSet(resultSet);
162  closeStatement(statement);
163  connection.close();
165  }
166 
167  return count;
168  }
169 
175  SleuthkitCase getSleuthkitCase() {
176  return this.db;
177  }
178 
192  public Account.Type addAccountType(String accountTypeName, String displayName) throws TskCoreException {
193  Account.Type accountType = new Account.Type(accountTypeName, displayName);
194 
195  // check if already in map
196  if (this.accountTypeToTypeIdMap.containsKey(accountType)) {
197  return accountType;
198  }
199 
200  CaseDbConnection connection = db.getConnection();
202  Statement s = null;
203  ResultSet rs = null;
204  try {
205  connection.beginTransaction();
206  s = connection.createStatement();
207  rs = connection.executeQuery(s, "SELECT * FROM account_types WHERE type_name = '" + accountTypeName + "'"); //NON-NLS
208  if (!rs.next()) {
209  rs.close();
210 
211  s.execute("INSERT INTO account_types (type_name, display_name) VALUES ( '" + accountTypeName + "', '" + displayName + "')"); //NON-NLS
212 
213  // Read back the typeID
214  rs = connection.executeQuery(s, "SELECT * FROM account_types WHERE type_name = '" + accountTypeName + "'"); //NON-NLS
215  rs.next();
216 
217  int typeID = rs.getInt("account_type_id");
218  accountType = new Account.Type(rs.getString("type_name"), rs.getString("display_name"));
219 
220  this.accountTypeToTypeIdMap.put(accountType, typeID);
221  this.typeNameToAccountTypeMap.put(accountTypeName, accountType);
222 
223  connection.commitTransaction();
224 
225  return accountType;
226  } else {
227  int typeID = rs.getInt("account_type_id");
228 
229  accountType = new Account.Type(rs.getString("type_name"), rs.getString("display_name"));
230  this.accountTypeToTypeIdMap.put(accountType, typeID);
231 
232  return accountType;
233  }
234  } catch (SQLException ex) {
235  connection.rollbackTransaction();
236  throw new TskCoreException("Error adding account type", ex);
237  } finally {
238  closeResultSet(rs);
239  closeStatement(s);
240  connection.close();
242  }
243  }
244 
262  public AccountFileInstance createAccountFileInstance(Account.Type accountType, String accountUniqueID, String moduleName, Content sourceFile) throws TskCoreException {
263 
264  // make or get the Account (unique at the case-level)
265  Account account = getOrCreateAccount(accountType, normalizeAccountID(accountType, accountUniqueID));
266 
267  /*
268  * make or get the artifact. Will not create one if it already exists
269  * for the sourceFile. Such as an email PST that has the same email
270  * address multiple times. Only one artifact is created for each email
271  * message in that PST.
272  */
273  BlackboardArtifact accountArtifact = getOrCreateAccountFileInstanceArtifact(accountType, normalizeAccountID(accountType, accountUniqueID), moduleName, sourceFile);
274 
275  // The account instance map was unused so we have removed it from the database,
276  // but we expect we may need it so I am preserving this method comment and usage here.
277  // add a row to Accounts to Instances mapping table
278  // @@@ BC: Seems like we should only do this if we had to create the artifact.
279  // But, it will probably fail to create a new one based on unique constraints.
280  // addAccountFileInstanceMapping(account.getAccountID(), accountArtifact.getArtifactID());
281  return new AccountFileInstance(accountArtifact, account);
282  }
283 
296  public Account getAccount(Account.Type accountType, String accountUniqueID) throws TskCoreException {
297  Account account = null;
298  CaseDbConnection connection = db.getConnection();
300  Statement s = null;
301  ResultSet rs = null;
302  try {
303  s = connection.createStatement();
304  rs = connection.executeQuery(s, "SELECT * FROM accounts WHERE account_type_id = " + getAccountTypeId(accountType)
305  + " AND account_unique_identifier = '" + normalizeAccountID(accountType, accountUniqueID) + "'"); //NON-NLS
306 
307  if (rs.next()) {
308  account = new Account(rs.getInt("account_id"), accountType,
309  rs.getString("account_unique_identifier"));
310  }
311  } catch (SQLException ex) {
312  throw new TskCoreException("Error getting account type id", ex);
313  } finally {
314  closeResultSet(rs);
315  closeStatement(s);
316  connection.close();
318  }
319 
320  return account;
321  }
322 
333 // public AccountFileInstance getAccountFileInstance(BlackboardArtifact artifact) throws TskCoreException {
334 // AccountFileInstance accountInstance = null;
335 // if (artifact.getArtifactTypeID() == BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()) {
336 // String accountTypeStr = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE)).getValueString();
337 // String accountID = artifact.getAttribute(new BlackboardAttribute.Type(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID)).getValueString();
338 // Account.Type accountType = getAccountType(accountTypeStr);
339 //
340 // Account account = getAccount(accountType, accountID);
341 // accountInstance = new AccountFileInstance(artifact, account);
342 // } else {
343 // throw new TskCoreException("Unexpected Artifact type = " + artifact.getArtifactTypeID());
344 // }
345 //
346 // return accountInstance;
347 // }
369  public void addRelationships(AccountFileInstance sender, List<AccountFileInstance> recipients,
370  BlackboardArtifact sourceArtifact, Relationship.Type relationshipType, long dateTime) throws TskCoreException, TskDataException {
371 
372  if (relationshipType.isCreatableFrom(sourceArtifact) == false) {
373  throw new TskDataException("Can not make a " + relationshipType.getDisplayName()
374  + " relationship from a" + sourceArtifact.getDisplayName());
375  }
376 
377  /*
378  * Enforce that all accounts and the relationship between them are from
379  * the same 'source'. This is required for the queries to work
380  * correctly.
381  */
382  // Currently we do not save the direction of communication
383  List<Long> accountIDs = new ArrayList<Long>();
384 
385  if (null != sender) {
386  accountIDs.add(sender.getAccount().getAccountID());
387  if (sender.getDataSourceObjectID() != sourceArtifact.getDataSourceObjectID()) {
388  throw new TskDataException("Sender and relationship are from different data sources :"
389  + "Sender source ID" + sender.getDataSourceObjectID() + " != relationship source ID" + sourceArtifact.getDataSourceObjectID());
390  }
391  }
392 
393  for (AccountFileInstance recipient : recipients) {
394  accountIDs.add(recipient.getAccount().getAccountID());
395  if (recipient.getDataSourceObjectID() != sourceArtifact.getDataSourceObjectID()) {
396  throw new TskDataException("Recipient and relationship are from different data sources :"
397  + "Recipient source ID" + recipient.getDataSourceObjectID() + " != relationship source ID" + sourceArtifact.getDataSourceObjectID());
398  }
399  }
400 
401  Set<UnorderedAccountPair> relationships = listToUnorderedPairs(accountIDs);
402  Iterator<UnorderedAccountPair> iter = relationships.iterator();
403 
404  while (iter.hasNext()) {
405  try {
406  UnorderedAccountPair accountPair = iter.next();
407  addAccountsRelationship(accountPair.getFirst(), accountPair.getSecond(),
408  sourceArtifact, relationshipType, dateTime);
409  } catch (TskCoreException ex) {
410  // @@@ This should probably not be caught and instead we stop adding
411  LOGGER.log(Level.WARNING, "Error adding relationship", ex); //NON-NLS
412  }
413  }
414  }
415 
428  private Account getOrCreateAccount(Account.Type accountType, String accountUniqueID) throws TskCoreException {
429  Account account = getAccount(accountType, accountUniqueID);
430  if (null == account) {
431  String query = " INTO accounts (account_type_id, account_unique_identifier) "
432  + "VALUES ( " + getAccountTypeId(accountType) + ", '"
433  + normalizeAccountID(accountType, accountUniqueID) + "'" + ")";
434  switch (db.getDatabaseType()) {
435  case POSTGRESQL:
436  query = "INSERT " + query + " ON CONFLICT DO NOTHING"; //NON-NLS
437  break;
438  case SQLITE:
439  query = "INSERT OR IGNORE " + query;
440  break;
441  default:
442  throw new TskCoreException("Unknown DB Type: " + db.getDatabaseType().name());
443  }
444 
445  CaseDbConnection connection = db.getConnection();
447  Statement s = null;
448  ResultSet rs = null;
449  try {
450  connection.beginTransaction();
451  s = connection.createStatement();
452 
453  s.execute(query);
454 
455  connection.commitTransaction();
456  account = getAccount(accountType, accountUniqueID);
457  } catch (SQLException ex) {
458  connection.rollbackTransaction();
459  throw new TskCoreException("Error adding an account", ex);
460  } finally {
461  closeResultSet(rs);
462  closeStatement(s);
463  connection.close();
465  }
466  }
467 
468  return account;
469  }
470 
485  BlackboardArtifact getOrCreateAccountFileInstanceArtifact(Account.Type accountType, String accountUniqueID, String moduleName, Content sourceFile) throws TskCoreException {
486 
487  // see if it already exists
488  BlackboardArtifact accountArtifact = getAccountFileInstanceArtifact(accountType, accountUniqueID, sourceFile);
489  if (null != accountArtifact) {
490  return accountArtifact;
491  }
492 
493  // Create a new artifact.
494  accountArtifact = db.newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT, sourceFile.getId());
495 
496  Collection<BlackboardAttribute> attributes = new ArrayList<BlackboardAttribute>();
497  attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE, moduleName, accountType.getTypeName()));
498  attributes.add(new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID, moduleName, accountUniqueID));
499  accountArtifact.addAttributes(attributes);
500 
501  return accountArtifact;
502  }
503 
517  private BlackboardArtifact getAccountFileInstanceArtifact(Account.Type accountType, String accountUniqueID, Content sourceFile) throws TskCoreException {
518  BlackboardArtifact accountArtifact = null;
519  CaseDbConnection connection = db.getConnection();
521  Statement s = null;
522  ResultSet rs = null;
523 
524  try {
525  s = connection.createStatement();
526  String queryStr = "SELECT artifacts.artifact_id AS artifact_id,"
527  + " artifacts.obj_id AS obj_id,"
528  + " artifacts.artifact_obj_id AS artifact_obj_id,"
529  + " artifacts.data_source_obj_id AS data_source_obj_id,"
530  + " artifacts.artifact_type_id AS artifact_type_id,"
531  + " artifacts.review_status_id AS review_status_id"
532  + " FROM blackboard_artifacts AS artifacts"
533  + " JOIN blackboard_attributes AS attr_account_type"
534  + " ON artifacts.artifact_id = attr_account_type.artifact_id"
535  + " JOIN blackboard_attributes AS attr_account_id"
536  + " ON artifacts.artifact_id = attr_account_id.artifact_id"
537  + " AND attr_account_id.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ID.getTypeID()
538  + " AND attr_account_id.value_text = '" + accountUniqueID + "'"
539  + " WHERE artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_ACCOUNT.getTypeID()
540  + " AND attr_account_type.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID()
541  + " AND attr_account_type.value_text = '" + accountType.getTypeName() + "'"
542  + " AND artifacts.obj_id = " + sourceFile.getId(); //NON-NLS
543 
544  rs = connection.executeQuery(s, queryStr); //NON-NLS
545  if (rs.next()) {
546  BlackboardArtifact.Type bbartType = db.getArtifactType(rs.getInt("artifact_type_id"));
547 
548  accountArtifact = new BlackboardArtifact(db, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
549  bbartType.getTypeID(), bbartType.getTypeName(), bbartType.getDisplayName(),
550  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id")));
551  }
552  } catch (SQLException ex) {
553  throw new TskCoreException("Error getting account", ex);
554  } finally {
555  closeResultSet(rs);
556  closeStatement(s);
557  connection.close();
559  }
560 
561  return accountArtifact;
562  }
563 
574  public Account.Type getAccountType(String accountTypeName) throws TskCoreException {
575  if (this.typeNameToAccountTypeMap.containsKey(accountTypeName)) {
576  return this.typeNameToAccountTypeMap.get(accountTypeName);
577  }
578 
579  CaseDbConnection connection = db.getConnection();
581  Statement s = null;
582  ResultSet rs = null;
583 
584  try {
585  s = connection.createStatement();
586  rs = connection.executeQuery(s, "SELECT account_type_id, type_name, display_name, value_type FROM account_types WHERE type_name = '" + accountTypeName + "'"); //NON-NLS
587  Account.Type accountType = null;
588  if (rs.next()) {
589  accountType = new Account.Type(accountTypeName, rs.getString("display_name"));
590  this.accountTypeToTypeIdMap.put(accountType, rs.getInt("account_type_id"));
591  this.typeNameToAccountTypeMap.put(accountTypeName, accountType);
592  }
593  return accountType;
594  } catch (SQLException ex) {
595  throw new TskCoreException("Error getting account type id", ex);
596  } finally {
597  closeResultSet(rs);
598  closeStatement(s);
599  connection.close();
601  }
602  }
603 
615  private Account getAccount(long account_id) throws TskCoreException {
616  Account account = null;
617  CaseDbConnection connection = db.getConnection();
619  Statement s = null;
620  ResultSet rs = null;
621 
622  try {
623  s = connection.createStatement();
624  rs = connection.executeQuery(s, "SELECT account_types.type_name as type_name,"
625  + " account_types.display_name as display_name,"
626  + " accounts.account_id as account_id,"
627  + " accounts.account_unique_identifier as account_unique_identifier"
628  + " FROM accounts as accounts"
629  + " JOIN account_types as account_types"
630  + " ON accounts.account_type_id = account_types.account_type_id"
631  + " WHERE accounts.account_id = " + account_id); //NON-NLS
632 
633  if (rs.next()) {
634  Account.Type accountType = new Account.Type(rs.getString("type_name"), rs.getString("display_name"));
635  account = new Account(rs.getInt("account_id"), accountType, rs.getString("account_unique_identifier"));
636  }
637  } catch (SQLException ex) {
638  throw new TskCoreException("Error getting account from account_id", ex);
639  } finally {
640  closeResultSet(rs);
641  closeStatement(s);
642  connection.close();
644  }
645 
646  return account;
647  }
648 
662  private void addAccountsRelationship(long account1_id, long account2_id, BlackboardArtifact relationshipaArtifact, Relationship.Type relationshipType, long dateTime) throws TskCoreException {
663  CaseDbConnection connection = db.getConnection();
665  Statement s = null;
666  ResultSet rs = null;
667 
668  try {
669  String dateTimeValStr = (dateTime > 0) ? Long.toString(dateTime) : "NULL";
670 
671  connection.beginTransaction();
672  s = connection.createStatement();
673  String query = "INTO account_relationships (account1_id, account2_id, relationship_source_obj_id, date_time, relationship_type, data_source_obj_id ) "
674  + "VALUES ( " + account1_id + ", " + account2_id + ", " + relationshipaArtifact.getId() + ", " + dateTimeValStr + ", " + relationshipType.getTypeID() + ", " + relationshipaArtifact.getDataSourceObjectID() + ")";
675  switch (db.getDatabaseType()) {
676  case POSTGRESQL:
677  query = "INSERT " + query + " ON CONFLICT DO NOTHING";
678  break;
679  case SQLITE:
680  query = "INSERT OR IGNORE " + query;
681  break;
682  default:
683  throw new TskCoreException("Unknown DB Type: " + db.getDatabaseType().name());
684  }
685  s.execute(query); //NON-NLS
686  connection.commitTransaction();
687  } catch (SQLException ex) {
688  connection.rollbackTransaction();
689  throw new TskCoreException("Error adding accounts relationship", ex);
690  } finally {
691  closeResultSet(rs);
692  closeStatement(s);
693  connection.close();
695  }
696  }
697 
712  public List<AccountDeviceInstance> getAccountDeviceInstancesWithRelationships(CommunicationsFilter filter) throws TskCoreException {
713  CaseDbConnection connection = db.getConnection();
715  Statement s = null;
716  ResultSet rs = null;
717 
718  try {
719  s = connection.createStatement();
720 
721  //set up applicable filters
722  Set<String> applicableInnerQueryFilters = new HashSet<String>(Arrays.asList(
723  CommunicationsFilter.DateRangeFilter.class.getName(),
724  CommunicationsFilter.DeviceFilter.class.getName(),
726  ));
727  String innerQueryfilterSQL = getCommunicationsFilterSQL(filter, applicableInnerQueryFilters);
728 
729  String innerQueryTemplate
730  = " SELECT %1$1s as account_id,"
731  + " data_source_obj_id"
732  + " FROM account_relationships as relationships"
733  + (innerQueryfilterSQL.isEmpty() ? "" : " WHERE " + innerQueryfilterSQL);
734 
735  String innerQuery1 = String.format(innerQueryTemplate, "account1_id");
736  String innerQuery2 = String.format(innerQueryTemplate, "account2_id");
737 
738  //this query groups by account_id and data_source_obj_id across both innerQueries
739  String combinedInnerQuery
740  = "SELECT count(*) as relationship_count, account_id, data_source_obj_id "
741  + " FROM ( " + innerQuery1 + " UNION " + innerQuery2 + " ) AS inner_union"
742  + " GROUP BY account_id, data_source_obj_id";
743 
744  // set up applicable filters
745  Set<String> applicableFilters = new HashSet<String>(Arrays.asList(
747  ));
748 
749  String filterSQL = getCommunicationsFilterSQL(filter, applicableFilters);
750 
751  String queryStr
752  = //account info
753  " accounts.account_id AS account_id,"
754  + " accounts.account_unique_identifier AS account_unique_identifier,"
755  //account type info
756  + " account_types.type_name AS type_name,"
757  //Account device instance info
758  + " relationship_count,"
759  + " data_source_info.device_id AS device_id"
760  + " FROM ( " + combinedInnerQuery + " ) AS account_device_instances"
761  + " JOIN accounts AS accounts"
762  + " ON accounts.account_id = account_device_instances.account_id"
763  + " JOIN account_types AS account_types"
764  + " ON accounts.account_type_id = account_types.account_type_id"
765  + " JOIN data_source_info AS data_source_info"
766  + " ON account_device_instances.data_source_obj_id = data_source_info.obj_id"
767  + (filterSQL.isEmpty() ? "" : " WHERE " + filterSQL);
768 
769  switch (db.getDatabaseType()) {
770  case POSTGRESQL:
771  queryStr = "SELECT DISTINCT ON ( accounts.account_id, data_source_info.device_id) " + queryStr;
772  break;
773  case SQLITE:
774  queryStr = "SELECT " + queryStr + " GROUP BY accounts.account_id, data_source_info.device_id";
775  break;
776  default:
777  throw new TskCoreException("Unknown DB Type: " + db.getDatabaseType().name());
778  }
779 
780  rs = connection.executeQuery(s, queryStr); //NON-NLS
781  ArrayList<AccountDeviceInstance> accountDeviceInstances = new ArrayList<AccountDeviceInstance>();
782  while (rs.next()) {
783  long account_id = rs.getLong("account_id");
784  String deviceID = rs.getString("device_id");
785  final String type_name = rs.getString("type_name");
786  final String account_unique_identifier = rs.getString("account_unique_identifier");
787 
788  Account.Type accountType = typeNameToAccountTypeMap.get(type_name);
789  Account account = new Account(account_id, accountType, account_unique_identifier);
790  accountDeviceInstances.add(new AccountDeviceInstance(account, deviceID));
791  }
792 
793  return accountDeviceInstances;
794  } catch (SQLException ex) {
795  throw new TskCoreException("Error getting account device instances. " + ex.getMessage(), ex);
796  } finally {
797  closeResultSet(rs);
798  closeStatement(s);
799  connection.close();
801  }
802  }
803 
818  public long getRelationshipSourcesCount(AccountDeviceInstance accountDeviceInstance, CommunicationsFilter filter) throws TskCoreException {
819 
820  long account_id = accountDeviceInstance.getAccount().getAccountID();
821 
822  // Get the list of Data source objects IDs correpsonding to this DeviceID.
823  String datasourceObjIdsCSV = StringUtils.buildCSVString(
824  db.getDataSourceObjIds(accountDeviceInstance.getDeviceId()));
825 
826  // set up applicable filters
827  Set<String> applicableFilters = new HashSet<String>(Arrays.asList(
829  CommunicationsFilter.DateRangeFilter.class.getName()
830  ));
831  String filterSQL = getCommunicationsFilterSQL(filter, applicableFilters);
832 
833  CaseDbConnection connection = db.getConnection();
835  Statement s = null;
836  ResultSet rs = null;
837 
838  try {
839  s = connection.createStatement();
840 
841  String queryStr
842  = "SELECT count(DISTINCT relationships.relationship_source_obj_id) as count "
843  + " FROM account_relationships AS relationships"
844  + " WHERE relationships.data_source_obj_id IN ( " + datasourceObjIdsCSV + " )"
845  + " AND ( relationships.account1_id = " + account_id
846  + " OR relationships.account2_id = " + account_id + " )"
847  + (filterSQL.isEmpty() ? "" : " AND " + filterSQL);
848 
849  rs = connection.executeQuery(s, queryStr); //NON-NLS
850  rs.next();
851  return (rs.getLong("count"));
852  } catch (SQLException ex) {
853  throw new TskCoreException("Error getting relationships count for account device instance. " + ex.getMessage(), ex);
854  } finally {
855  closeResultSet(rs);
856  closeStatement(s);
857  connection.close();
859  }
860  }
861 
876  public Set<Content> getRelationshipSources(Set<AccountDeviceInstance> accountDeviceInstanceList, CommunicationsFilter filter) throws TskCoreException {
877 
878  if (accountDeviceInstanceList.isEmpty()) {
879  //log this?
880  return Collections.emptySet();
881  }
882 
883  Map<Long, Set<Long>> accountIdToDatasourceObjIdMap = new HashMap<Long, Set<Long>>();
884  for (AccountDeviceInstance accountDeviceInstance : accountDeviceInstanceList) {
885  long accountID = accountDeviceInstance.getAccount().getAccountID();
886  List<Long> dataSourceObjIds = db.getDataSourceObjIds(accountDeviceInstance.getDeviceId());
887 
888  if (accountIdToDatasourceObjIdMap.containsKey(accountID)) {
889  accountIdToDatasourceObjIdMap.get(accountID).addAll(dataSourceObjIds);
890  } else {
891  accountIdToDatasourceObjIdMap.put(accountID, new HashSet<Long>(dataSourceObjIds));
892  }
893  }
894 
895  List<String> adiSQLClauses = new ArrayList<String>();
896  for (Map.Entry<Long, Set<Long>> entry : accountIdToDatasourceObjIdMap.entrySet()) {
897  final Long accountID = entry.getKey();
898  String datasourceObjIdsCSV = StringUtils.buildCSVString(entry.getValue());
899 
900  adiSQLClauses.add(
901  "( ( relationships.data_source_obj_id IN ( " + datasourceObjIdsCSV + " ) )"
902  + " AND ( relationships.account1_id = " + accountID
903  + " OR relationships.account2_id = " + accountID + " ) )"
904  );
905  }
906  String adiSQLClause = StringUtils.joinAsStrings(adiSQLClauses, " OR ");
907 
908  // set up applicable filters
909  Set<String> applicableFilters = new HashSet<String>(Arrays.asList(
911  CommunicationsFilter.DateRangeFilter.class.getName()
912  ));
913  String filterSQL = getCommunicationsFilterSQL(filter, applicableFilters);
914 
915  CaseDbConnection connection = db.getConnection();
917  Statement s = null;
918  ResultSet rs = null;
919 
920  try {
921  s = connection.createStatement();
922  String queryStr
923  = "SELECT DISTINCT artifacts.artifact_id AS artifact_id,"
924  + " artifacts.obj_id AS obj_id,"
925  + " artifacts.artifact_obj_id AS artifact_obj_id,"
926  + " artifacts.data_source_obj_id AS data_source_obj_id, "
927  + " artifacts.artifact_type_id AS artifact_type_id, "
928  + " artifacts.review_status_id AS review_status_id "
929  + " FROM blackboard_artifacts as artifacts"
930  + " JOIN account_relationships AS relationships"
931  + " ON artifacts.artifact_obj_id = relationships.relationship_source_obj_id"
932  // append sql to restrict search to specified account device instances
933  + " WHERE (" + adiSQLClause + " )"
934  // plus other filters
935  + (filterSQL.isEmpty() ? "" : " AND (" + filterSQL + " )");
936 
937  rs = connection.executeQuery(s, queryStr); //NON-NLS
938  Set<Content> relationshipSources = new HashSet<Content>();
939  while (rs.next()) {
940  BlackboardArtifact.Type bbartType = db.getArtifactType(rs.getInt("artifact_type_id"));
941  relationshipSources.add(new BlackboardArtifact(db, rs.getLong("artifact_id"),
942  rs.getLong("obj_id"), rs.getLong("artifact_obj_id"),
943  rs.getLong("data_source_obj_id"), bbartType.getTypeID(),
944  bbartType.getTypeName(), bbartType.getDisplayName(),
945  BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
946  }
947 
948  return relationshipSources;
949  } catch (SQLException ex) {
950  throw new TskCoreException("Error getting relationships for account. " + ex.getMessage(), ex);
951  } finally {
952  closeResultSet(rs);
953  closeStatement(s);
954  connection.close();
956  }
957  }
958 
966  int getAccountTypeId(Account.Type accountType) {
967  if (accountTypeToTypeIdMap.containsKey(accountType)) {
968  return accountTypeToTypeIdMap.get(accountType);
969  }
970 
971  return 0;
972  }
973 
981  private Set<UnorderedAccountPair> listToUnorderedPairs(List<Long> account_ids) {
982  Set<UnorderedAccountPair> relationships = new HashSet<UnorderedAccountPair>();
983 
984  for (int i = 0; i < account_ids.size(); i++) {
985  for (int j = i + 1; j < account_ids.size(); j++) {
986  relationships.add(new UnorderedAccountPair(account_ids.get(i), account_ids.get(j)));
987  }
988  }
989 
990  return relationships;
991  }
992 
993  private String normalizeAccountID(Account.Type accountType, String accountUniqueID) {
994  String normailzeAccountID = accountUniqueID;
995 
996  if (accountType.equals(Account.Type.PHONE)) {
997  normailzeAccountID = normalizePhoneNum(accountUniqueID);
998  } else if (accountType.equals(Account.Type.EMAIL)) {
999  normailzeAccountID = normalizeEmailAddress(accountUniqueID);
1000  }
1001 
1002  return normailzeAccountID;
1003  }
1004 
1005  private String normalizePhoneNum(String phoneNum) {
1006  String normailzedPhoneNum = phoneNum.replaceAll("\\D", "");
1007 
1008  if (phoneNum.startsWith("+")) {
1009  normailzedPhoneNum = "+" + normailzedPhoneNum;
1010  }
1011 
1012  return normailzedPhoneNum;
1013  }
1014 
1015  private String normalizeEmailAddress(String emailAddress) {
1016  String normailzedEmailAddr = emailAddress.toLowerCase();
1017 
1018  return normailzedEmailAddr;
1019  }
1020 
1033  private String getCommunicationsFilterSQL(CommunicationsFilter commFilter, Set<String> applicableFilters) {
1034  if (null == commFilter || commFilter.getAndFilters().isEmpty()) {
1035  return "";
1036  }
1037 
1038  String sqlStr = "";
1039  StringBuilder sqlSB = new StringBuilder();
1040  boolean first = true;
1041  for (CommunicationsFilter.SubFilter subFilter : commFilter.getAndFilters()) {
1042 
1043  // If the filter is applicable
1044  if (applicableFilters.contains(subFilter.getClass().getName())) {
1045  String subfilterSQL = subFilter.getSQL(this);
1046  if (!subfilterSQL.isEmpty()) {
1047  if (first) {
1048  first = false;
1049  } else {
1050  sqlSB.append(" AND ");
1051  }
1052  sqlSB.append("( ");
1053  sqlSB.append(subfilterSQL);
1054  sqlSB.append(" )");
1055  }
1056  }
1057  }
1058 
1059  if (!sqlSB.toString().isEmpty()) {
1060  sqlStr = "( " + sqlSB.toString() + " )";
1061  }
1062  return sqlStr;
1063  }
1064 
1069  private final class UnorderedAccountPair {
1070 
1071  private final long account1_id;
1072  private final long account2_id;
1073 
1074  UnorderedAccountPair(long account1_id, long account2_id) {
1075  this.account1_id = account1_id;
1076  this.account2_id = account2_id;
1077  }
1078 
1079  @Override
1080  public int hashCode() {
1081  return new Long(account1_id).hashCode() + new Long(account2_id).hashCode();
1082  }
1083 
1084  @Override
1085  public boolean equals(Object other) {
1086  if (other == this) {
1087  return true;
1088  }
1089  if (!(other instanceof UnorderedAccountPair)) {
1090  return false;
1091  }
1092 
1093  UnorderedAccountPair otherPair = (UnorderedAccountPair) other;
1094  return ((account1_id == otherPair.account1_id && account2_id == otherPair.account2_id)
1095  || (account1_id == otherPair.account2_id && account2_id == otherPair.account1_id));
1096  }
1097 
1098  public long getFirst() {
1099  return account1_id;
1100  }
1101 
1102  public long getSecond() {
1103  return account2_id;
1104  }
1105  }
1106 
1107 // /**
1108 // * Get all account instances of a given type
1109 // *
1110 // * @param accountType account type
1111 // *
1112 // * @return List <Account.Type>, list of accounts
1113 // *
1114 // * @throws TskCoreException exception thrown if a critical error occurs
1115 // * within TSK core
1116 // */
1117 // public List<AccountInstance> getAccountInstances(Account.Type accountType) throws TskCoreException {
1118 // List<AccountInstance> accountInstances = new ArrayList<AccountInstance>();
1119 //
1120 // // First get all accounts of the type
1121 // List<Account> accounts = getAccounts(accountType);
1122 //
1123 // // get all instances for each account
1124 // for (Account account : accounts) {
1125 // List<Long> accountInstanceIds = getAccountInstanceIds(account.getAccountID());
1126 //
1127 // for (long artifact_id : accountInstanceIds) {
1128 // accountInstances.add(new AccountFileInstance(db, db.getBlackboardArtifact(artifact_id), account));
1129 // }
1130 // }
1131 //
1132 // return accountInstances;
1133 // }
1134 // /**
1135 // * Given an account ID, returns the ids of all instances of the account
1136 // *
1137 // * @param account_id account id
1138 // *
1139 // * @return List <Long>, list of account instance IDs
1140 // *
1141 // * @throws TskCoreException exception thrown if a critical error occurs
1142 // * within TSK core
1143 // */
1144 // List<Long> getAccountInstanceIds(long account_id) throws TskCoreException {
1145 // ArrayList<Long> accountInstanceIDs = new ArrayList<Long>();
1146 // CaseDbConnection connection = db.getConnection();
1147 // db.acquireSingleUserCaseReadLock();
1148 // Statement s = null;
1149 // ResultSet rs = null;
1150 //
1151 // try {
1152 // s = connection.createStatement();
1153 // rs = connection.executeQuery(s, "SELECT * FROM account_to_instances_map WHERE account_id = " + account_id); //NON-NLS
1154 // while (rs.next()) {
1155 // accountInstanceIDs.add(rs.getLong("account_instance_id"));
1156 // }
1157 // return accountInstanceIDs;
1158 // } catch (SQLException ex) {
1159 // throw new TskCoreException("Error getting account_instance_id from by account_id. " + ex.getMessage(), ex);
1160 // } finally {
1161 // closeResultSet(rs);
1162 // closeStatement(s);
1163 // connection.close();
1164 // db.releaseSingleUserCaseReadLock();
1165 // }
1166 // }
1167 // /**
1168 // * Get all account types in use
1169 // *
1170 // * @return List <Account.Type>, list of account types in use
1171 // *
1172 // * @throws TskCoreException exception thrown if a critical error occurs
1173 // * within TSK core
1174 // */
1175 // public List<Account.Type> getAccountTypesInUse() throws TskCoreException {
1176 // String query = "SELECT DISTINCT value_text FROM blackboard_attributes "
1177 // + "WHERE attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_ACCOUNT_TYPE.getTypeID();
1178 // CaseDbConnection connection = db.getConnection();
1179 // db.acquireSingleUserCaseReadLock();
1180 // Statement s = null;
1181 // ResultSet rs = null;
1182 //
1183 // try {
1184 // s = connection.createStatement();
1185 // rs = connection.executeQuery(s, query);
1186 // ArrayList<Account.Type> usedAccountTypes = new ArrayList<Account.Type>();
1187 // while (rs.next()) {
1188 // String accountTypeString = rs.getString("value_text");
1189 // usedAccountTypes.add(getAccountType(accountTypeString));
1190 // }
1191 //
1192 // return usedAccountTypes;
1193 // } catch (SQLException ex) {
1194 // throw new TskCoreException("Error getting account types in use", ex);
1195 // } finally {
1196 // closeResultSet(rs);
1197 // closeStatement(s);
1198 // connection.close();
1199 // db.releaseSingleUserCaseReadLock();
1200 // }
1201 // }
1202 // /**
1203 // * Get all accounts of given type
1204 // *
1205 // * @param accountType account type
1206 // *
1207 // * @return List <Account.Type>, list of accounts
1208 // *
1209 // * @throws TskCoreException exception thrown if a critical error occurs
1210 // * within TSK core
1211 // */
1212 // public List<Account> getAccounts(Account.Type accountType) throws TskCoreException {
1213 // ArrayList<Account> accounts = new ArrayList<Account>();
1214 // CaseDbConnection connection = db.getConnection();
1215 // db.acquireSingleUserCaseReadLock();
1216 // Statement s = null;
1217 // ResultSet rs = null;
1218 //
1219 // try {
1220 // s = connection.createStatement();
1221 // rs = connection.executeQuery(s, "SELECT * FROM accounts WHERE account_type_id = " + getAccountTypeId(accountType)); //NON-NLS
1222 // while (rs.next()) {
1223 // accounts.add(new Account(rs.getInt("account_id"), accountType,
1224 // rs.getString("account_unique_identifier")));
1225 //
1226 // }
1227 //
1228 // return accounts;
1229 // } catch (SQLException ex) {
1230 // throw new TskCoreException("Error getting accounts by type. " + ex.getMessage(), ex);
1231 // } finally {
1232 // closeResultSet(rs);
1233 // closeStatement(s);
1234 // connection.close();
1235 // db.releaseSingleUserCaseReadLock();
1236 // }
1237 // }
1238 // /**
1239 // * Get all accounts that have a relationship with the given account
1240 // *
1241 // * @param account account for which to search relationships
1242 // *
1243 // * @return list of accounts with relationships to the given account
1244 // *
1245 // * @throws TskCoreException exception thrown if a critical error occurs
1246 // * within TSK core
1247 // */
1248 // public List<Account> getAccountsWithRelationship(Account account) throws TskCoreException {
1249 // return getAccountsWithRelationship(account.getAccountID());
1250 // }
1251 // /**
1252 // * Get all account that have a relationship with a given account
1253 // *
1254 // * @param account_id account id
1255 // *
1256 // * @return List<Account>, list of accounts
1257 // *
1258 // * @throws TskCoreException exception thrown if a critical error occurs
1259 // * within TSK core
1260 // */
1261 // List<Account> getAccountsWithRelationship(long accountID) throws TskCoreException {
1262 // CaseDbConnection connection = db.getConnection();
1263 // db.acquireSingleUserCaseReadLock();
1264 // Statement s = null;
1265 // ResultSet rs = null;
1266 //
1267 // try {
1268 // s = connection.createStatement();
1269 // rs = connection.executeQuery(s, "SELECT account1_id, account2_id "
1270 // + " FROM relationships"
1271 // + " WHERE account1_id = " + accountID
1272 // + " OR account2_id = " + accountID); //NON-NLS
1273 //
1274 // ArrayList<Account> accounts = new ArrayList<Account>();
1275 // while (rs.next()) {
1276 // long otherAccountID = (accountID == rs.getLong("account1_id")) ? rs.getLong("account2_id") : rs.getLong("account1_id");
1277 // Account account = getAccount(otherAccountID);
1278 // if (null != account) {
1279 // accounts.add(account);
1280 // }
1281 // }
1282 //
1283 // return accounts;
1284 // } catch (SQLException ex) {
1285 // throw new TskCoreException("Error getting relationships by account by ID. " + ex.getMessage(), ex);
1286 // } finally {
1287 // closeResultSet(rs);
1288 // closeStatement(s);
1289 // connection.close();
1290 // db.releaseSingleUserCaseReadLock();
1291 // }
1292 // }
1293 // /**
1294 // * Return folders found in the email source file
1295 // *
1296 // * @param srcObjID pbjectID of the email PST/Mbox source file
1297 // *
1298 // * @return list of message folders
1299 // *
1300 // * @throws TskCoreException exception thrown if a critical error occurs
1301 // * within TSK core
1302 // */
1303 // public List<MessageFolder> getMessageFolders(long srcObjID) throws TskCoreException {
1304 // CaseDbConnection connection = db.getConnection();
1305 // db.acquireSingleUserCaseReadLock();
1306 // Statement s = null;
1307 // ResultSet rs = null;
1308 //
1309 // try {
1310 // s = connection.createStatement();
1311 // rs = connection.executeQuery(s, "SELECT DISTINCT attributes.value_text AS folder_path"
1312 // + " FROM blackboard_artifacts AS artifacts"
1313 // + " JOIN blackboard_attributes AS attributes"
1314 // + " ON artifacts.artifact_id = attributes.artifact_id"
1315 // + " AND artifacts.obj_id = " + srcObjID
1316 // + " WHERE artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
1317 // + " AND attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()
1318 // ); //NON-NLS
1319 //
1320 // ArrayList<MessageFolder> messageFolders = new ArrayList<MessageFolder>();
1321 // while (rs.next()) {
1322 // String folder = rs.getString("folder_path");
1323 //
1324 // // TBD: check if this folder has subfolders and set hasSubFolders accordingly.
1325 // messageFolders.add(new MessageFolder(folder, srcObjID));
1326 // }
1327 //
1328 // return messageFolders;
1329 // } catch (SQLException ex) {
1330 // throw new TskCoreException("Error getting message folders. " + ex.getMessage(), ex);
1331 // } finally {
1332 // closeResultSet(rs);
1333 // closeStatement(s);
1334 // connection.close();
1335 // db.releaseSingleUserCaseReadLock();
1336 // }
1337 //
1338 // }
1339 //
1340 // /**
1341 // * Return subfolders found in the email source file under the specified
1342 // * folder
1343 // *
1344 // * @param srcObjID objectID of the email PST/Mbox source file
1345 // * @param parentfolder parent folder of messages to return
1346 // *
1347 // * @return list of message sub-folders
1348 // *
1349 // * @throws TskCoreException exception thrown if a critical error occurs
1350 // * within TSK core
1351 // */
1352 // public List<MessageFolder> getMessageFolders(long srcObjID, MessageFolder parentfolder) throws TskCoreException {
1353 // CaseDbConnection connection = db.getConnection();
1354 // db.acquireSingleUserCaseReadLock();
1355 // Statement s = null;
1356 // ResultSet rs = null;
1357 //
1358 // try {
1359 // s = connection.createStatement();
1360 // rs = connection.executeQuery(s, "SELECT DISTINCT attributes.value_text AS folder_path"
1361 // + " FROM blackboard_artifacts AS artifacts"
1362 // + " JOIN blackboard_attributes AS attributes"
1363 // + " ON artifacts.artifact_id = attributes.artifact_id"
1364 // + " AND artifacts.obj_id = " + srcObjID
1365 // + " WHERE artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
1366 // + " AND attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()
1367 // + " AND attributes.value_text LIKE '" + parentfolder.getName() + "%'"
1368 // ); //NON-NLS
1369 //
1370 // ArrayList<MessageFolder> messageFolders = new ArrayList<MessageFolder>();
1371 // while (rs.next()) {
1372 // String folder = rs.getString("folder_path");
1373 // messageFolders.add(new MessageFolder(folder, srcObjID));
1374 // }
1375 //
1376 // return messageFolders;
1377 // } catch (SQLException ex) {
1378 // throw new TskCoreException("Error getting message folders. " + ex.getMessage(), ex);
1379 // } finally {
1380 // closeResultSet(rs);
1381 // closeStatement(s);
1382 // connection.close();
1383 // db.releaseSingleUserCaseReadLock();
1384 // }
1385 //
1386 // }
1387 // /**
1388 // * Return email messages under given folder
1389 // *
1390 // * @param parentfolder parent folder of messages to return
1391 // *
1392 // * @return list of messages
1393 // *
1394 // * @throws TskCoreException exception thrown if a critical error occurs
1395 // * within TSK core
1396 // */
1397 // public List<BlackboardArtifact> getMessages(MessageFolder parentfolder) throws TskCoreException {
1398 // CaseDbConnection connection = db.getConnection();
1399 // db.acquireSingleUserCaseReadLock();
1400 // Statement s = null;
1401 // ResultSet rs = null;
1402 //
1403 // try {
1404 // s = connection.createStatement();
1405 // rs = connection.executeQuery(s, "SELECT artifacts.artifact_id AS artifact_id,"
1406 // + " artifacts.obj_id AS obj_id,"
1407 // + " artifacts.artifact_obj_id AS artifact_obj_id,"
1408 // + " artifacts.data_source_obj_id AS data_source_obj_id, "
1409 // + " artifacts.artifact_type_id AS artifact_type_id, "
1410 // + " artifacts.review_status_id AS review_status_id, "
1411 // + " FROM blackboard_artifacts AS artifacts"
1412 // + " JOIN blackboard_attributes AS attributes"
1413 // + " ON artifacts.artifact_id = attributes.artifact_id"
1414 // + " AND artifacts.artifact_type_id = " + BlackboardArtifact.ARTIFACT_TYPE.TSK_EMAIL_MSG.getTypeID()
1415 // + " WHERE attributes.attribute_type_id = " + BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PATH.getTypeID()
1416 // + " AND attributes.value_text = '" + parentfolder.getName() + "' "
1417 // ); //NON-NLS
1418 //
1419 // ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
1420 // while (rs.next()) {
1421 // BlackboardArtifact.Type bbartType = db.getArtifactType(rs.getInt("artifact_type_id"));
1422 // artifacts.add(new BlackboardArtifact(db, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
1423 // bbartType.getTypeID(), bbartType.getTypeName(), bbartType.getDisplayName(),
1424 // BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
1425 // }
1426 //
1427 // return artifacts;
1428 // } catch (SQLException ex) {
1429 // throw new TskCoreException("Error getting messages. " + ex.getMessage(), ex);
1430 // } finally {
1431 // closeResultSet(rs);
1432 // closeStatement(s);
1433 // connection.close();
1434 // db.releaseSingleUserCaseReadLock();
1435 // }
1436 //
1437 // }
1438 // /**
1439 // * Returns unique relation types between two accounts
1440 // *
1441 // * @param account1 account
1442 // * @param account2 account
1443 // *
1444 // * @return list of unique relationship types between two accounts
1445 // *
1446 // * @throws TskCoreException exception thrown if a critical error occurs
1447 // * within TSK core
1448 // */
1449 // public List<BlackboardArtifact.Type> getRelationshipTypes(Account account1, Account account2) throws TskCoreException {
1450 // return getRelationshipTypes(account1.getAccountID(), account2.getAccountID());
1451 // }
1452 // /**
1453 // * Returns unique relation types between two accounts
1454 // *
1455 // * @param account1_id account1 artifact ID
1456 // * @param account2_id account2 artifact ID
1457 // *
1458 // * @throws TskCoreException exception thrown if a critical error occurs
1459 // * within TSK core
1460 // */
1461 // List<BlackboardArtifact.Type> getRelationshipTypes(long account1_id, long account2_id) throws TskCoreException {
1462 // CaseDbConnection connection = db.getConnection();
1463 // db.acquireSingleUserCaseReadLock();
1464 // Statement s = null;
1465 // ResultSet rs = null;
1466 //
1467 // try {
1468 // s = connection.createStatement();
1469 // rs = connection.executeQuery(s, "SELECT DISTINCT artifacts.artifact_id AS artifact_id,"
1470 // + " artifacts.obj_id AS obj_id,"
1471 // + " artifacts.artifact_obj_id AS artifact_obj_id,"
1472 // + " artifacts.artifact_type_id AS artifact_type_id,"
1473 // + " artifacts.review_status_id AS review_status_id"
1474 // + " FROM blackboard_artifacts AS artifacts"
1475 // + " JOIN relationships AS relationships"
1476 // + " ON artifacts.artifact_obj_id = relationships.relationship_source_obj_id"
1477 // + " WHERE relationships.account1_id IN ( " + account1_id + ", " + account2_id + " )"
1478 // + " AND relationships.account2_id IN ( " + account1_id + ", " + account2_id + " )"
1479 // ); //NON-NLS
1480 //
1481 // ArrayList<BlackboardArtifact.Type> artifactTypes = new ArrayList<BlackboardArtifact.Type>();
1482 // while (rs.next()) {
1483 // BlackboardArtifact.Type bbartType = db.getArtifactType(rs.getInt("artifact_type_id"));
1484 // artifactTypes.add(bbartType);
1485 // }
1486 //
1487 // return artifactTypes;
1488 // } catch (SQLException ex) {
1489 // throw new TskCoreException("Error getting relationship types." + ex.getMessage(), ex);
1490 // } finally {
1491 // closeResultSet(rs);
1492 // closeStatement(s);
1493 // connection.close();
1494 // db.releaseSingleUserCaseReadLock();
1495 // }
1496 // }
1497 // /**
1498 // * Returns relationships between two accounts
1499 // *
1500 // * @param account1_id account_id for account1
1501 // * @param account2_id account_id for account2
1502 // *
1503 // * @throws TskCoreException exception thrown if a critical error occurs
1504 // * within TSK core
1505 // */
1506 // public List<BlackboardArtifact> getRelationships(long account1_id, long account2_id) throws TskCoreException {
1507 // CaseDbConnection connection = db.getConnection();
1508 // db.acquireSingleUserCaseReadLock();
1509 // Statement s = null;
1510 // ResultSet rs = null;
1511 //
1512 // try {
1513 // s = connection.createStatement();
1514 // rs = connection.executeQuery(s, "SELECT artifacts.artifact_id AS artifact_id,"
1515 // + " artifacts.obj_id AS obj_id,"
1516 // + " artifacts.artifact_obj_id AS artifact_obj_id,"
1517 // + " artifacts.data_source_obj_id AS data_source_obj_id,"
1518 // + " artifacts.artifact_type_id AS artifact_type_id,"
1519 // + " artifacts.review_status_id AS review_status_id"
1520 // + " FROM blackboard_artifacts AS artifacts"
1521 // + " JOIN relationships AS relationships"
1522 // + " ON artifacts.artifact_obj_id = relationships.relationship_source_obj_id"
1523 // + " WHERE relationships.account1_id IN ( " + account1_id + ", " + account2_id + " )"
1524 // + " AND relationships.account2_id IN ( " + account1_id + ", " + account2_id + " )"
1525 // ); //NON-NLS
1526 //
1527 // ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
1528 // while (rs.next()) {
1529 // BlackboardArtifact.Type bbartType = db.getArtifactType(rs.getInt("artifact_type_id"));
1530 // artifacts.add(new BlackboardArtifact(db, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
1531 // bbartType.getTypeID(), bbartType.getTypeName(), bbartType.getDisplayName(),
1532 // BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
1533 // }
1534 //
1535 // return artifacts;
1536 // } catch (SQLException ex) {
1537 // throw new TskCoreException("Error getting relationships bteween accounts. " + ex.getMessage(), ex);
1538 // } finally {
1539 // closeResultSet(rs);
1540 // closeStatement(s);
1541 // connection.close();
1542 // db.releaseSingleUserCaseReadLock();
1543 // }
1544 // }
1545 // /**
1546 // * Returns relationships, of given type, between two accounts
1547 // *
1548 // * @param account1_id account1 artifact ID
1549 // * @param account2_id account2 artifact ID
1550 // * @param artifactType artifact type
1551 // *
1552 // *
1553 // * @throws TskCoreException exception thrown if a critical error occurs
1554 // * within TSK core
1555 // */
1556 // public List<BlackboardArtifact> getRelationshipsOfType(long account1_id, long account2_id, BlackboardArtifact.Type artifactType) throws TskCoreException {
1557 // CaseDbConnection connection = db.getConnection();
1558 // db.acquireSingleUserCaseReadLock();
1559 // Statement s = null;
1560 // ResultSet rs = null;
1561 //
1562 // try {
1563 // s = connection.createStatement();
1564 // rs = connection.executeQuery(s, "SELECT artifacts.artifact_id AS artifact_id,"
1565 // + " artifacts.obj_id AS obj_id,"
1566 // + " artifacts.artifact_obj_id AS artifact_obj_id,"
1567 // + " artifacts.data_source_obj_id AS data_source_obj_id,"
1568 // + " artifacts.artifact_type_id AS artifact_type_id,"
1569 // + " artifacts.review_status_id AS review_status_id"
1570 // + " FROM relationships AS relationships"
1571 // + " WHERE artifacts.artifact_type_id = " + artifactType.getTypeID()
1572 // + " AND relationships.account1_id IN ( " + account1_id + ", " + account2_id + " )"
1573 // + " AND relationships.account2_id IN ( " + account1_id + ", " + account2_id + " )"
1574 // ); //NON-NLS
1575 //
1576 // ArrayList<BlackboardArtifact> artifacts = new ArrayList<BlackboardArtifact>();
1577 // while (rs.next()) {
1578 // BlackboardArtifact.Type bbartType = db.getArtifactType(rs.getInt("artifact_type_id"));
1579 // artifacts.add(new BlackboardArtifact(db, rs.getLong("artifact_id"), rs.getLong("obj_id"), rs.getLong("artifact_obj_id"), rs.getLong("data_source_obj_id"),
1580 // bbartType.getTypeID(), bbartType.getTypeName(), bbartType.getDisplayName(),
1581 // BlackboardArtifact.ReviewStatus.withID(rs.getInt("review_status_id"))));
1582 // }
1583 //
1584 // return artifacts;
1585 // } catch (SQLException ex) {
1586 // throw new TskCoreException("Error getting relationships bteween accounts. " + ex.getMessage(), ex);
1587 // } finally {
1588 // closeResultSet(rs);
1589 // closeStatement(s);
1590 // connection.close();
1591 // db.releaseSingleUserCaseReadLock();
1592 // }
1593 // }
1594 // /**
1595 // * Get the number of relationships found on the given device
1596 // *
1597 // * @param deviceId device to look up
1598 // *
1599 // * RAMAN TBD: add filter param
1600 // *
1601 // * @return number of account relationships found on this device
1602 // *
1603 // * @throws org.sleuthkit.datamodel.TskCoreException
1604 // */
1605 // public long getRelationshipsCountByDevice(String deviceId) throws TskCoreException {
1606 // List<Long> ds_ids = db.getDataSourceObjIds(deviceId);
1607 // String datasource_obj_ids_list = buildCSVString(ds_ids);
1608 // CaseDbConnection connection = db.getConnection();
1609 // db.acquireSingleUserCaseReadLock();
1610 // Statement s = null;
1611 // ResultSet rs = null;
1612 //
1613 // try {
1614 // s = connection.createStatement();
1615 // String queryStr = "SELECT COUNT(*) AS count "
1616 // + " FROM blackboard_artifacts as artifacts"
1617 // + " JOIN relationships AS relationships"
1618 // + " ON artifacts.artifact_id = relationships.relationship_source_obj_id"
1619 // + " WHERE artifacts.data_source_obj_id IN ( " + datasource_obj_ids_list + " )"
1620 // + " AND artifacts.artifact_type_id IN ( " + RELATIONSHIP_ARTIFACT_TYPE_IDS_CSV_STR + " )";
1621 //
1622 // System.out.println("RAMAN QueryStr = " + queryStr);
1623 // System.out.println("");
1624 //
1625 // // RAMAN TBD: add SQL from filters
1626 // rs = connection.executeQuery(s, queryStr); //NON-NLS
1627 // rs.next();
1628 //
1629 // return (rs.getLong("count"));
1630 // } catch (SQLException ex) {
1631 // throw new TskCoreException("Error getting relationships bteween accounts. " + ex.getMessage(), ex);
1632 // } finally {
1633 // closeResultSet(rs);
1634 // closeStatement(s);
1635 // connection.close();
1636 // db.releaseSingleUserCaseReadLock();
1637 // }
1638 // }
1639 // /**
1640 // *
1641 // * @param accountId - database row id
1642 // * @param accountInstanceId - Artifact ID of instance
1643 // *
1644 // * @throws TskCoreException
1645 // */
1646 // private void addAccountFileInstanceMapping(long accountId, long accountInstanceId) throws TskCoreException {
1647 // CaseDbConnection connection = db.getConnection();
1648 // db.acquireSingleUserCaseWriteLock();
1649 // Statement s = null;
1650 // ResultSet rs = null;
1651 //
1652 // try {
1653 // connection.beginTransaction();
1654 // s = connection.createStatement();
1655 //
1656 // s.execute("INSERT INTO account_to_instances_map (account_id, account_instance_id) VALUES ( " + accountId + ", " + accountInstanceId + " )"); //NON-NLS
1657 // connection.commitTransaction();
1658 // } catch (SQLException ex) {
1659 // connection.rollbackTransaction();
1660 // throw new TskCoreException("Error adding an account to instance mapping", ex);
1661 // } finally {
1662 // closeResultSet(rs);
1663 // closeStatement(s);
1664 // connection.close();
1665 // db.releaseSingleUserCaseWriteLock();
1666 // }
1667 // }
1668 }
BlackboardArtifact getAccountFileInstanceArtifact(Account.Type accountType, String accountUniqueID, Content sourceFile)
Set< Content > getRelationshipSources(Set< AccountDeviceInstance > accountDeviceInstanceList, CommunicationsFilter filter)
Account getAccount(Account.Type accountType, String accountUniqueID)
void addAttributes(Collection< BlackboardAttribute > attributes)
Account.Type addAccountType(String accountTypeName, String displayName)
String getCommunicationsFilterSQL(CommunicationsFilter commFilter, Set< String > applicableFilters)
Set< UnorderedAccountPair > listToUnorderedPairs(List< Long > account_ids)
Account getOrCreateAccount(Account.Type accountType, String accountUniqueID)
void addRelationships(AccountFileInstance sender, List< AccountFileInstance > recipients, BlackboardArtifact sourceArtifact, Relationship.Type relationshipType, long dateTime)
final Map< String, Account.Type > typeNameToAccountTypeMap
static final Account.Type PHONE
Definition: Account.java:50
AccountFileInstance createAccountFileInstance(Account.Type accountType, String accountUniqueID, String moduleName, Content sourceFile)
String normalizeAccountID(Account.Type accountType, String accountUniqueID)
static final Set< Integer > RELATIONSHIP_ARTIFACT_TYPE_IDS
final Map< Account.Type, Integer > accountTypeToTypeIdMap
Account.Type getAccountType(String accountTypeName)
BlackboardArtifact newBlackboardArtifact(int artifactTypeID, long obj_id)
static final List< Account.Type > PREDEFINED_ACCOUNT_TYPES
Definition: Account.java:59
BlackboardArtifact.Type getArtifactType(String artTypeName)
void addAccountsRelationship(long account1_id, long account2_id, BlackboardArtifact relationshipaArtifact, Relationship.Type relationshipType, long dateTime)
long getRelationshipSourcesCount(AccountDeviceInstance accountDeviceInstance, CommunicationsFilter filter)
List< AccountDeviceInstance > getAccountDeviceInstancesWithRelationships(CommunicationsFilter filter)
static final Account.Type EMAIL
Definition: Account.java:51

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