19 package org.sleuthkit.autopsy.modules.android;
 
   22 import java.io.IOException;
 
   23 import java.sql.Connection;
 
   24 import java.sql.DriverManager;
 
   25 import java.sql.ResultSet;
 
   26 import java.sql.SQLException;
 
   27 import java.sql.Statement;
 
   28 import java.util.Arrays;
 
   29 import java.util.List;
 
   30 import java.util.logging.Level;
 
   31 import org.openide.util.NbBundle.Messages;
 
   42 import org.
sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE;
 
   50 class CallLogAnalyzer {
 
   52     private static final String moduleName = AndroidModuleFactory.getModuleName();
 
   53     private static final Logger logger = Logger.getLogger(CallLogAnalyzer.class.getName());
 
   54     private static Blackboard blackboard;
 
   59     private static final Iterable<String> tableNames = Arrays.asList(
"calls", 
"logs"); 
 
   61     public static void findCallLogs(Content dataSource, FileManager fileManager,
 
   62             IngestJobContext context) {
 
   63         blackboard = Case.getCurrentCase().getServices().getBlackboard();
 
   65             List<AbstractFile> absFiles = fileManager.findFiles(dataSource, 
"logs.db"); 
 
   66             absFiles.addAll(fileManager.findFiles(dataSource, 
"contacts.db")); 
 
   67             absFiles.addAll(fileManager.findFiles(dataSource, 
"contacts2.db")); 
 
   68             for (AbstractFile abstractFile : absFiles) {
 
   70                     File file = 
new File(Case.getCurrentCase().getTempDirectory(), abstractFile.getName());
 
   71                     ContentUtils.writeToFile(abstractFile, file, context::dataSourceIngestIsCancelled);
 
   72                     findCallLogsInDB(file.toString(), abstractFile);
 
   73                 } 
catch (IOException e) {
 
   74                     logger.log(Level.SEVERE, 
"Error writing temporary call log db to disk", e); 
 
   77         } 
catch (TskCoreException e) {
 
   78             logger.log(Level.SEVERE, 
"Error finding call logs", e); 
 
   82     @Messages({
"CallLogAnalyzer.indexError.message=Failed to index call log artifact for keyword search."})
 
   83     private static void findCallLogsInDB(String DatabasePath, AbstractFile f) {
 
   85         if (DatabasePath == null || DatabasePath.isEmpty()) {
 
   88         try (Connection connection = DriverManager.getConnection(
"jdbc:sqlite:" + DatabasePath); 
 
   89                 Statement statement = connection.createStatement();) {
 
   91             for (String tableName : tableNames) {
 
   92                 try (ResultSet resultSet = statement.executeQuery(
 
   93                         "SELECT number,date,duration,type, name FROM " + tableName + 
" ORDER BY date DESC;");) { 
 
   94                     logger.log(Level.INFO, 
"Reading call log from table {0} in db {1}", 
new Object[]{tableName, DatabasePath}); 
 
   95                     while (resultSet.next()) {
 
   96                         Long date = resultSet.getLong(
"date") / 1000;
 
   97                         final CallDirection direction = CallDirection.fromType(resultSet.getInt(
"type")); 
 
   98                         String directionString = direction != null ? direction.getDisplayName() : 
"";
 
   99                         final String number = resultSet.getString(
"number"); 
 
  100                         final long duration = resultSet.getLong(
"duration"); 
 
  101                         final String name = resultSet.getString(
"name"); 
 
  104                             BlackboardArtifact bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CALLLOG); 
 
  105                             if (direction == CallDirection.OUTGOING) {
 
  106                                 bba.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_TO, moduleName, number));
 
  108                                 bba.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_PHONE_NUMBER_FROM, moduleName, number));
 
  110                             bba.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_START, moduleName, date));
 
  111                             bba.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DATETIME_END, moduleName, duration + date));
 
  112                             bba.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_DIRECTION, moduleName, directionString));
 
  113                             bba.addAttribute(
new BlackboardAttribute(ATTRIBUTE_TYPE.TSK_NAME, moduleName, name));
 
  117                                 blackboard.indexArtifact(bba);
 
  118                             } 
catch (Blackboard.BlackboardException ex) {
 
  119                                 logger.log(Level.SEVERE, 
"Unable to index blackboard artifact " + bba.getArtifactID(), ex); 
 
  120                                 MessageNotifyUtil.Notify.error(
 
  121                                         Bundle.CallLogAnalyzer_indexError_message(), bba.getDisplayName());
 
  123                         } 
catch (TskCoreException ex) {
 
  124                             logger.log(Level.SEVERE, 
"Error posting call log record to the Blackboard", ex); 
 
  127                 } 
catch (SQLException e) {
 
  128                     logger.log(Level.WARNING, String.format(
"Could not read table %s in db %s", tableName, DatabasePath), e); 
 
  131         } 
catch (SQLException e) {
 
  132             logger.log(Level.SEVERE, 
"Could not parse call log; error connecting to db " + DatabasePath, e); 
 
  138         INCOMING(1, 
"Incoming"), 
OUTGOING(2, 
"Outgoing"), MISSED(3, 
"Missed"); 
 
  150             this.displayName = displayName;
 
CallDirection(int type, String displayName)
static CallDirection fromType(int t)