"""SQLite parser plugin for Android Burner database files."""
from dfdatetime import java_time as dfdatetime_java_time
from plaso.containers import events
from plaso.parsers import sqlite
from plaso.parsers.sqlite_plugins import interface
[docs]
class AndroidBurnerEventData(events.EventData):
"""Android Burner event data.
Attributes:
alias (str): Alias or nickname.
creation_time (dfdatetime.DateTimeValues): Creation date and time.
expiration_time (dfdatetime.DateTimeValues): Expiration date and time.
last_updated_time (dfdatetime.DateTimeValues): Last update date and time.
name (str): Name of the burner.
phone_number (str): Associated phone number.
total_minutes (int): Total minutes available for calls.
user_identifier (str): User identifier.
voicemail_url (str): URL for accessing the voicemail associated with the
burner.
"""
DATA_TYPE = 'android:burners'
[docs]
def __init__(self):
"""Initializes event data."""
super().__init__(data_type=self.DATA_TYPE)
self.alias = None
self.creation_time = None
self.expiration_time = None
self.last_updated_time = None
self.name = None
self.phone_number = None
self.total_minutes = None
self.user_identifier = None
self.voicemail_url = None
[docs]
class AndroidBurnerPlugin(interface.SQLitePlugin):
"""SQLite parser plugin for Android communication information database files.
The Android communication information database file is typically stored in:
burners.db
"""
NAME = 'android_communication_information'
DATA_FORMAT = 'Android communication information SQLite database file'
REQUIRED_STRUCTURE = {
'burners': frozenset([
'_id', 'phone_number_id', 'voicemail_url', 'user_id', 'name', 'alias',
'features', 'total_minutes', 'expiration_date', 'date_created',
'last_updated_date', 'renewal_date'])
}
QUERIES = [(
('SELECT _id AS id, phone_number_id, voicemail_url, user_id, name, '
'alias, features, total_minutes, expiration_date, date_created, '
'last_updated_date, renewal_date FROM burners'), '_ParseBurnersRow')]
SCHEMAS = [{
'android_metadata': (
'CREATE TABLE android_metadata (locale TEXT)'),
'burners': (
'CREATE TABLE burners(_id integer primary key autoincrement, '
'burner_id text not null unique, phone_number_id text not null, '
'voicemail_url text, user_id text not null, name text, alias text, '
'features text not null, total_minutes integer not null, '
'remaining_minutes integer not null, total_texts integer not null, '
'remaining_texts integer not null, expiration_date integer not '
'null, ringer integer default 1, notifications integer default 1, '
'disabled integer default 0, date_created integer not null, '
'last_updated_date integer, extension_count integer default 0, '
'renewal_date integer default 0, auto_reply_active integer default '
'0, auto_reply_text text, caller_id_enabled integer default 0, '
'useSip integer default 0, hexColor integer, call_forward_status '
'text)'),
'connections': (
'CREATE TABLE connections(_id integer primary key autoincrement, '
'user_id integer not null, burner_id integer not null, name text, '
'handle text, image_url text, service_name text not null, status '
'text)'),
'contacts': (
'CREATE TABLE contacts(_id integer primary key autoincrement, '
'contact_id text not null unique, name text not null, phone_number '
'text not null, burner_id text, date_created integer not null, '
'last_updated_date integer not null, blocked integer default 0, '
'muted integer default 0, notes text, images text)'),
'messages': (
'CREATE TABLE messages(_id integer primary key autoincrement, '
'message_id text not null unique, state integer default 0, message '
'text not null, contact_phone_number text not null, connected '
'integer default 0, message_type integer not null, '
'contact_burner_id text, voice_url text, date_created integer not '
'null, last_updated_date integer not null, read integer default 0, '
'user_id text not null, sid text, burner_id text not null, duration '
'integer, direction integer not null, asset_url text, send_status '
'integer default 0 )'),
'subscriptions': (
'CREATE TABLE subscriptions(_id integer primary key autoincrement, '
'subscription_id text not null unique, sku text not null, receipt '
'text not null, burner_ids text, renewal_date integer, '
'burner_assigned_in_period integer, store text not null,canceled '
'integer not null, cancellation_date integer)')}]
def _GetDateTimeRowValue(self, query_hash, row, value_name):
"""Retrieves a date and time value from the row.
Args:
query_hash (int): hash of the query, that uniquely identifies the query
that produced the row.
row (sqlite3.Row): row.
value_name (str): name of the value.
Returns:
dfdatetime.JavaTime: date and time value or None if not available.
"""
timestamp = self._GetRowValue(query_hash, row, value_name)
if timestamp is None:
return None
return dfdatetime_java_time.JavaTime(timestamp=timestamp)
def _ParseBurnersRow(self, parser_mediator, query, row, **unused_kwargs):
"""Parses a burners 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)
# TODO: parse features.
# TODO: parse renewal_date.
event_data = AndroidBurnerEventData()
event_data.alias = self._GetRowValue(query_hash, row, 'alias')
event_data.creation_time = self._GetDateTimeRowValue(
query_hash, row, 'date_created')
event_data.expiration_time = self._GetDateTimeRowValue(
query_hash, row, 'expiration_date')
event_data.last_updated_time = self._GetDateTimeRowValue(
query_hash, row, 'last_updated_date')
event_data.name = self._GetRowValue(query_hash, row, 'name')
event_data.phone_number = self._GetRowValue(
query_hash, row, 'phone_number_id')
event_data.total_minutes = self._GetRowValue(
query_hash, row, 'total_minutes')
event_data.user_identifier = self._GetRowValue(query_hash, row, 'user_id')
event_data.voicemail_url = self._GetRowValue(
query_hash, row, 'voicemail_url')
parser_mediator.ProduceEventData(event_data)
sqlite.SQLiteParser.RegisterPlugin(AndroidBurnerPlugin)