# -*- coding: utf-8 -*-
"""This file contains a parser for the MacOS application usage.
The application usage is stored in SQLite database files named
/var/db/application_usage.sqlite
"""
from __future__ import unicode_literals
from dfdatetime import posix_time as dfdatetime_posix_time
from plaso.containers import events
from plaso.containers import time_events
from plaso.parsers import sqlite
from plaso.parsers.sqlite_plugins import interface
[docs]class MacOSApplicationUsageEventData(events.EventData):
"""MacOS application usage event data.
Attributes:
application (str): name of the application.
app_version (str): version of the application.
bundle_id (str): bundle identifier of the application.
count (int): TODO: number of times what?
"""
DATA_TYPE = 'macosx:application_usage'
def __init__(self):
"""Initializes event data."""
super(MacOSApplicationUsageEventData, self).__init__(
data_type=self.DATA_TYPE)
self.application = None
self.app_version = None
self.bundle_id = None
self.count = None
[docs]class ApplicationUsagePlugin(interface.SQLitePlugin):
"""Parse Application Usage history files.
Application usage is a SQLite database that logs down entries
triggered by NSWorkspaceWillLaunchApplicationNotification and
NSWorkspaceDidTerminateApplicationNotification NSWorkspace notifications by
crankd.
See the code here:
http://code.google.com/p/google-macops/source/browse/trunk/crankd/\
ApplicationUsage.py
Default installation: /var/db/application_usage.sqlite
"""
NAME = 'appusage'
DESCRIPTION = 'Parser for MacOS application usage SQLite database files.'
# Define the needed queries.
QUERIES = [(
('SELECT last_time, event, bundle_id, app_version, app_path, '
'number_times FROM application_usage ORDER BY last_time'),
'ParseApplicationUsageRow')]
# The required tables.
REQUIRED_TABLES = frozenset(['application_usage'])
SCHEMAS = [{
'application_usage': (
'CREATE TABLE application_usage (event TEXT, bundle_id TEXT, '
'app_version TEXT, app_path TEXT, last_time INTEGER DEFAULT 0, '
'number_times INTEGER DEFAULT 0, PRIMARY KEY (event, bundle_id))')}]
# pylint 1.9.3 wants a docstring for kwargs, but this is not useful to add.
# pylint: disable=missing-param-doc
[docs] def ParseApplicationUsageRow(
self, parser_mediator, query, row, **unused_kwargs):
"""Parses an application usage 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: replace usage by definition(s) in eventdata. Not sure which values
# it will hold here.
application_name = self._GetRowValue(query_hash, row, 'event')
usage = 'Application {0:s}'.format(application_name)
event_data = MacOSApplicationUsageEventData()
event_data.application = self._GetRowValue(query_hash, row, 'app_path')
event_data.app_version = self._GetRowValue(query_hash, row, 'app_version')
event_data.bundle_id = self._GetRowValue(query_hash, row, 'bundle_id')
event_data.count = self._GetRowValue(query_hash, row, 'number_times')
event_data.query = query
timestamp = self._GetRowValue(query_hash, row, 'last_time')
date_time = dfdatetime_posix_time.PosixTime(timestamp=timestamp)
event = time_events.DateTimeValuesEvent(date_time, usage)
parser_mediator.ProduceEventWithEventData(event, event_data)
sqlite.SQLiteParser.RegisterPlugin(ApplicationUsagePlugin)