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)