Source code for plaso.parsers.sqlite_plugins.android_calls

"""SQLite parser plugin for Android call history database files.

The Android call history database file is typically stored in:
  contacts2.db
"""

from dfdatetime import java_time as dfdatetime_java_time

from plaso.containers import events
from plaso.lib import definitions
from plaso.parsers import sqlite
from plaso.parsers.sqlite_plugins import interface


[docs] class AndroidCallEventData(events.EventData): """Android Call event data. Attributes: call_type (int): type of call, such as: Incoming, Outgoing, or Missed. duration (int): number of seconds the call lasted. end_time (dfdatetime.DateTimeValues): date and time the call was stopped. name (str): name associated to the remote party. number (str): phone number associated to the remote party. offset (str): identifier of the row, from which the event data was extracted. query (str): SQL query that was used to obtain the event data. start_time (dfdatetime.DateTimeValues): date and time the call was started. """ DATA_TYPE = "android:event:call"
[docs] def __init__(self): """Initializes event data.""" super().__init__(data_type=self.DATA_TYPE) self.call_type = None self.duration = None self.end_time = None self.name = None self.number = None self.offset = None self.query = None self.start_time = None
[docs] class AndroidCallPlugin(interface.SQLitePlugin): """SQLite parser plugin for Android call history database files.""" NAME = "android_calls" DATA_FORMAT = "Android call history SQLite database (contacts2.db) file" REQUIRED_STRUCTURE = { "calls": frozenset(["date", "duration", "_id", "name", "number", "type"]) } QUERIES = [ ( "SELECT _id, date, duration, name, number, type FROM calls", "_ParseCallsRow", ) ] SCHEMAS = [ { "_sync_state": ( "CREATE TABLE _sync_state (_id INTEGER PRIMARY KEY, account_name " "TEXT NOT NULL, account_type TEXT NOT NULL, data TEXT, " "UNIQUE(account_name, account_type))" ), "_sync_state_metadata": ( "CREATE TABLE _sync_state_metadata (version INTEGER)" ), "accounts": ( "CREATE TABLE accounts (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "account_name TEXT, account_type TEXT, data_set TEXT)" ), "agg_exceptions": ( "CREATE TABLE agg_exceptions (_id INTEGER PRIMARY KEY " "AUTOINCREMENT, type INTEGER NOT NULL, raw_contact_id1 INTEGER " "REFERENCES raw_contacts(_id), raw_contact_id2 INTEGER REFERENCES " "raw_contacts(_id))" ), "android_metadata": ("CREATE TABLE android_metadata (locale TEXT)"), "calls": ( "CREATE TABLE calls (_id INTEGER PRIMARY KEY AUTOINCREMENT, number " "TEXT, date INTEGER, duration INTEGER, type INTEGER, new INTEGER, " "name TEXT, numbertype INTEGER, numberlabel TEXT, countryiso TEXT, " "voicemail_uri TEXT, is_read INTEGER, geocoded_location TEXT, " "lookup_uri TEXT, matched_number TEXT, normalized_number TEXT, " "photo_id INTEGER NOT NULL DEFAULT 0, formatted_number TEXT, _data " "TEXT, has_content INTEGER, mime_type TEXT, source_data TEXT, " "source_package TEXT, state INTEGER)" ), "contacts": ( "CREATE TABLE contacts (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "name_raw_contact_id INTEGER REFERENCES raw_contacts(_id), photo_id " "INTEGER REFERENCES data(_id), photo_file_id INTEGER REFERENCES " "photo_files(_id), custom_ringtone TEXT, send_to_voicemail INTEGER " "NOT NULL DEFAULT 0, times_contacted INTEGER NOT NULL DEFAULT 0, " "last_time_contacted INTEGER, starred INTEGER NOT NULL DEFAULT 0, " "has_phone_number INTEGER NOT NULL DEFAULT 0, lookup TEXT, " "status_update_id INTEGER REFERENCES data(_id), " "contact_last_updated_timestamp INTEGER)" ), "data": ( "CREATE TABLE data (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "package_id INTEGER REFERENCES package(_id), mimetype_id INTEGER " "REFERENCES mimetype(_id) NOT NULL, raw_contact_id INTEGER " "REFERENCES raw_contacts(_id) NOT NULL, is_read_only INTEGER NOT " "NULL DEFAULT 0, is_primary INTEGER NOT NULL DEFAULT 0, " "is_super_primary INTEGER NOT NULL DEFAULT 0, data_version INTEGER " "NOT NULL DEFAULT 0, data1 TEXT, data2 TEXT, data3 TEXT, data4 " "TEXT, data5 TEXT, data6 TEXT, data7 TEXT, data8 TEXT, data9 TEXT, " "data10 TEXT, data11 TEXT, data12 TEXT, data13 TEXT, data14 TEXT, " "data15 TEXT, data_sync1 TEXT, data_sync2 TEXT, data_sync3 TEXT, " "data_sync4 TEXT )" ), "data_usage_stat": ( "CREATE TABLE data_usage_stat(stat_id INTEGER PRIMARY KEY " "AUTOINCREMENT, data_id INTEGER NOT NULL, usage_type INTEGER NOT " "NULL DEFAULT 0, times_used INTEGER NOT NULL DEFAULT 0, " "last_time_used INTEGER NOT NULL DEFAULT 0, FOREIGN KEY(data_id) " "REFERENCES data(_id))" ), "default_directory": ( "CREATE TABLE default_directory (_id INTEGER PRIMARY KEY)" ), "deleted_contacts": ( "CREATE TABLE deleted_contacts (contact_id INTEGER PRIMARY KEY, " "contact_deleted_timestamp INTEGER NOT NULL default 0)" ), "directories": ( "CREATE TABLE directories(_id INTEGER PRIMARY KEY AUTOINCREMENT, " "packageName TEXT NOT NULL, authority TEXT NOT NULL, typeResourceId " "INTEGER, typeResourceName TEXT, accountType TEXT, accountName " "TEXT, displayName TEXT, exportSupport INTEGER NOT NULL DEFAULT 0, " "shortcutSupport INTEGER NOT NULL DEFAULT 0, photoSupport INTEGER " "NOT NULL DEFAULT 0)" ), "groups": ( "CREATE TABLE groups (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "package_id INTEGER REFERENCES package(_id), account_name STRING " "DEFAULT NULL, account_type STRING DEFAULT NULL, data_set STRING " "DEFAULT NULL, sourceid TEXT, version INTEGER NOT NULL DEFAULT 1, " "dirty INTEGER NOT NULL DEFAULT 0, title TEXT, title_res INTEGER, " "notes TEXT, system_id TEXT, deleted INTEGER NOT NULL DEFAULT 0, " "group_visible INTEGER NOT NULL DEFAULT 0, should_sync INTEGER NOT " "NULL DEFAULT 1, auto_add INTEGER NOT NULL DEFAULT 0, favorites " "INTEGER NOT NULL DEFAULT 0, group_is_read_only INTEGER NOT NULL " "DEFAULT 0, sync1 TEXT, sync2 TEXT, sync3 TEXT, sync4 TEXT , " "account_id INTEGER REFERENCES accounts(_id))" ), "mimetypes": ( "CREATE TABLE mimetypes (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "mimetype TEXT NOT NULL)" ), "name_lookup": ( "CREATE TABLE name_lookup (data_id INTEGER REFERENCES data(_id) NOT " "NULL, raw_contact_id INTEGER REFERENCES raw_contacts(_id) NOT " "NULL, normalized_name TEXT NOT NULL, name_type INTEGER NOT NULL, " "PRIMARY KEY (data_id, normalized_name, name_type))" ), "nickname_lookup": ( "CREATE TABLE nickname_lookup (name TEXT, cluster TEXT)" ), "packages": ( "CREATE TABLE packages (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "package TEXT NOT NULL)" ), "phone_lookup": ( "CREATE TABLE phone_lookup (data_id INTEGER REFERENCES data(_id) " "NOT NULL, raw_contact_id INTEGER REFERENCES raw_contacts(_id) NOT " "NULL, normalized_number TEXT NOT NULL, min_match TEXT NOT NULL)" ), "photo_files": ( "CREATE TABLE photo_files (_id INTEGER PRIMARY KEY AUTOINCREMENT, " "height INTEGER NOT NULL, width INTEGER NOT NULL, filesize INTEGER " "NOT NULL)" ), "properties": ( "CREATE TABLE properties (property_key TEXT PRIMARY KEY, " "property_value TEXT )" ), } ] def _GetEndTimeValue(self, query_hash, row): """Retrieves the end date and time value. Args: query_hash (int): hash of the query, that uniquely identifies the query that produced the row. row (sqlite3.Row): row. Returns: dfdatetime.JavaTime: date and time value or None if not available. """ date = self._GetRowValue(query_hash, row, "date") duration = self._GetRowValue(query_hash, row, "duration") if None in (date, duration): return None # date is in milliseconds and duration in seconds. timestamp = date + (duration * definitions.MILLISECONDS_PER_SECOND) return dfdatetime_java_time.JavaTime(timestamp=timestamp) def _ParseCallsRow(self, parser_mediator, query, row, **unused_kwargs): """Parses a Call record row. Args: parser_mediator (ParserMediator): mediates interactions between parsers and other components, such as storage and dfVFS. query (str): query that created the row. row (sqlite3.Row): row. """ query_hash = hash(query) event_data = AndroidCallEventData() event_data.call_type = self._GetRowValue(query_hash, row, "type") event_data.duration = self._GetRowValue(query_hash, row, "duration") event_data.end_time = self._GetEndTimeValue(query_hash, row) event_data.name = self._GetRowValue(query_hash, row, "name") event_data.number = self._GetRowValue(query_hash, row, "number") event_data.offset = self._GetRowValue(query_hash, row, "_id") event_data.query = query event_data.start_time = self._GetJavaTimeRowValue(query_hash, row, "date") parser_mediator.ProduceEventData(event_data)
sqlite.SQLiteParser.RegisterPlugin(AndroidCallPlugin)