19 package org.sleuthkit.autopsy.modules.android;
22 import java.sql.Connection;
23 import java.sql.DatabaseMetaData;
24 import java.sql.DriverManager;
25 import java.sql.ResultSet;
26 import java.sql.SQLException;
27 import java.sql.Statement;
28 import java.util.List;
29 import java.util.logging.Level;
30 import org.openide.util.NbBundle.Messages;
48 class ContactAnalyzer {
50 private static final String moduleName = AndroidModuleFactory.getModuleName();
51 private static final Logger logger = Logger.getLogger(ContactAnalyzer.class.getName());
53 public static void findContacts(Content dataSource, FileManager fileManager,
54 IngestJobContext context) {
55 List<AbstractFile> absFiles;
57 absFiles = fileManager.findFiles(dataSource,
"contacts.db");
58 absFiles.addAll(fileManager.findFiles(dataSource,
"contacts2.db"));
59 if (absFiles.isEmpty()) {
62 for (AbstractFile AF : absFiles) {
64 File jFile =
new File(Case.getCurrentCase().getTempDirectory(), AF.getName());
65 ContentUtils.writeToFile(AF, jFile, context::dataSourceIngestIsCancelled);
66 findContactsInDB(jFile.toString(), AF);
67 }
catch (Exception e) {
68 logger.log(Level.SEVERE,
"Error parsing Contacts", e);
71 }
catch (TskCoreException e) {
72 logger.log(Level.SEVERE,
"Error finding Contacts", e);
83 @Messages({
"ContactAnalyzer.indexError.message=Failed to index contact artifact for keyword search."})
84 private static void findContactsInDB(String databasePath, AbstractFile f) {
85 Connection connection = null;
86 ResultSet resultSet = null;
87 Statement statement = null;
88 Blackboard blackboard = Case.getCurrentCase().getServices().getBlackboard();
90 if (databasePath == null || databasePath.isEmpty()) {
94 Class.forName(
"org.sqlite.JDBC");
95 connection = DriverManager.getConnection(
"jdbc:sqlite:" + databasePath);
96 statement = connection.createStatement();
97 }
catch (ClassNotFoundException | SQLException e) {
98 logger.log(Level.SEVERE,
"Error opening database", e);
106 Boolean column_found =
false;
107 DatabaseMetaData metadata = connection.getMetaData();
108 ResultSet columnListResultSet = metadata.getColumns(null, null,
"contacts", null);
109 while (columnListResultSet.next()) {
110 if (columnListResultSet.getString(
"COLUMN_NAME").equals(
"name_raw_contact_id")) {
116 resultSet = statement.executeQuery(
117 "SELECT mimetype,data1, name_raw_contact.display_name AS display_name \n"
118 +
"FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n"
119 +
"JOIN raw_contacts AS name_raw_contact ON(name_raw_contact_id=name_raw_contact._id) "
120 +
"LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n"
121 +
"LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n"
122 +
"WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n"
123 +
"ORDER BY name_raw_contact.display_name ASC;");
125 resultSet = statement.executeQuery(
126 "SELECT mimetype,data1, raw_contacts.display_name AS display_name \n"
127 +
"FROM raw_contacts JOIN contacts ON (raw_contacts.contact_id=contacts._id) \n"
128 +
"LEFT OUTER JOIN data ON (data.raw_contact_id=raw_contacts._id) \n"
129 +
"LEFT OUTER JOIN mimetypes ON (data.mimetype_id=mimetypes._id) \n"
130 +
"WHERE mimetype = 'vnd.android.cursor.item/phone_v2' OR mimetype = 'vnd.android.cursor.item/email_v2'\n"
131 +
"ORDER BY raw_contacts.display_name ASC;");
134 BlackboardArtifact bba;
135 bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
140 while (resultSet.next()) {
141 name = resultSet.getString(
"display_name");
142 data1 = resultSet.getString(
"data1");
143 mimetype = resultSet.getString(
"mimetype");
144 if (name.equals(oldName) ==
false) {
145 bba = f.newArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_CONTACT);
146 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_NAME, moduleName, name));
148 if (mimetype.equals(
"vnd.android.cursor.item/phone_v2")) {
149 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_PHONE_NUMBER, moduleName, data1));
151 bba.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_EMAIL, moduleName, data1));
157 blackboard.indexArtifact(bba);
158 }
catch (Blackboard.BlackboardException ex) {
159 logger.log(Level.SEVERE,
"Unable to index blackboard artifact " + bba.getArtifactID(), ex);
160 MessageNotifyUtil.Notify.error(
161 Bundle.ContactAnalyzer_indexError_message(), bba.getDisplayName());
165 }
catch (SQLException e) {
166 logger.log(Level.WARNING,
"Unable to execute contacts SQL query against {0} : {1}",
new Object[]{databasePath, e});
167 }
catch (TskCoreException e) {
168 logger.log(Level.SEVERE,
"Error posting to blackboard", e);
171 if (resultSet != null) {
176 }
catch (Exception e) {
177 logger.log(Level.SEVERE,
"Error closing database", e);