11# -*- coding: utf-8 -*-
22"""IPS file parser plugin for Apple crash recovery report."""
33
4- import pyparsing
5-
6- from dfdatetime import time_elements as dfdatetime_time_elements
7-
84from plaso .containers import events
95from plaso .parsers import ips_parser
106from plaso .parsers .ips_plugins import interface
@@ -17,7 +13,7 @@ class AppleRecoveryLogdEvent(events.EventData):
1713 application_name (str): name of the application.
1814 application_version (str): version of the application.
1915 bug_type (str): type of bug.
20- crash_reporter_key (str):
16+ crash_reporter_key (str): Key of the crash reporter.
2117 device_model (str): model of the device.
2218 event_time (dfdatetime.DateTimeValues): date and time of the crash report.
2319 exception_type (str): type of the exception that caused the crash.
@@ -54,82 +50,14 @@ def __init__(self):
5450class AppleRecoveryLogdIPSPlugin (interface .IPSPlugin ):
5551 """Parses Apple Crash logs from IPS file."""
5652
57- NAME = 'apple_crash_log'
58- DATA_FORMAT = 'IPS application crash log'
59-
60- ENCODING = 'utf-8'
53+ NAME = 'apple_recovery_ips'
54+ DATA_FORMAT = 'IPS recovery logd crash log'
6155
6256 REQUIRED_HEADER_KEYS = [
6357 'app_name' , 'app_version' , 'bug_type' , 'incident_id' , 'os_version' ,
6458 'timestamp' ]
6559 REQUIRED_CONTENT_KEYS = [
66- 'captureTime' , 'modelCode' , 'os_version' , 'pid' , 'procLaunch' , ]
67-
68- _TWO_DIGITS = pyparsing .Word (pyparsing .nums , exact = 2 ).setParseAction (
69- lambda tokens : int (tokens [0 ], 10 ))
70-
71- _FOUR_DIGITS = pyparsing .Word (pyparsing .nums , exact = 4 ).setParseAction (
72- lambda tokens : int (tokens [0 ], 10 ))
73-
74- TIMESTAMP_GRAMMAR = (
75- _FOUR_DIGITS .setResultsName ('year' ) + pyparsing .Suppress ('-' ) +
76- _TWO_DIGITS .setResultsName ('month' ) + pyparsing .Suppress ('-' ) +
77- _TWO_DIGITS .setResultsName ('day' ) +
78- _TWO_DIGITS .setResultsName ('hours' ) + pyparsing .Suppress (':' ) +
79- _TWO_DIGITS .setResultsName ('minutes' ) + pyparsing .Suppress (':' ) +
80- _TWO_DIGITS .setResultsName ('seconds' ) + pyparsing .Suppress ('.' ) +
81- _FOUR_DIGITS .setResultsName ('fraction' ) +
82- pyparsing .Word (
83- pyparsing .nums + '+' + '-' ).setResultsName ('timezone_delta' ))
84-
85- def __init__ (self ):
86- """Initializes a text parser plugin."""
87- super (AppleRecoveryLogdIPSPlugin , self ).__init__ ()
88- self ._event_data = None
89-
90- def _ParseTimestampValue (self , parser_mediator , timestamp_text ):
91- """Parses a timestamp string.
92-
93- Args:
94- parser_mediator (ParserMediator): parser mediator.
95- timestamp_text (str): the timestamp to parse.
96-
97- Returns:
98- dfdatetime.TimeElements: date and time
99- or None if not available.
100- """
101- # dfDateTime takes the time zone offset as number of minutes relative from
102- # UTC. So for Easter Standard Time (EST), which is UTC-5:00 the sign needs
103- # to be converted, to +300 minutes.
104-
105- parsed_timestamp = self .TIMESTAMP_GRAMMAR .parseString (timestamp_text )
106-
107- try :
108- time_delta_hours = int (parsed_timestamp ['timezone_delta' ][:3 ], 10 )
109- time_delta_minutes = int (parsed_timestamp ['timezone_delta' ][3 :], 10 )
110- except (TypeError , ValueError ):
111- parser_mediator .ProduceExtractionWarning (
112- 'unsupported timezone offset value' )
113- return None
114-
115- time_zone_offset = (time_delta_hours * - 60 ) + time_delta_minutes
116-
117- try :
118- milliseconds = round (parsed_timestamp ['fraction' ]/ 10 )
119-
120- time_element_object = dfdatetime_time_elements .TimeElementsInMilliseconds (
121- time_elements_tuple = (
122- parsed_timestamp ['year' ], parsed_timestamp ['month' ],
123- parsed_timestamp ['day' ], parsed_timestamp ['hours' ],
124- parsed_timestamp ['minutes' ], parsed_timestamp ['seconds' ],
125- milliseconds ),
126- time_zone_offset = time_zone_offset )
127-
128- except (TypeError , ValueError ):
129- parser_mediator .ProduceExtractionWarning ('unsupported date time value' )
130- return None
131-
132- return time_element_object
60+ 'captureTime' , 'modelCode' , 'pid' , 'procLaunch' ]
13361
13462 # pylint: disable=unused-argument
13563 def Process (self , parser_mediator , ips_file = None , ** unused_kwargs ):
@@ -144,13 +72,11 @@ def Process(self, parser_mediator, ips_file=None, **unused_kwargs):
14472 if ips_file is None :
14573 raise ValueError ('Missing ips_file value' )
14674
147- # This will raise if unhandled keyword arguments are passed.
148- super (AppleRecoveryLogdIPSPlugin , self ).Process (parser_mediator )
149-
15075 event_data = AppleRecoveryLogdEvent ()
15176 event_data .application_name = ips_file .header .get ('app_name' )
15277 event_data .application_version = ips_file .header .get ('app_version' )
15378 event_data .bug_type = ips_file .header .get ('bug_type' )
79+ event_data .crash_reporter_key = ips_file .content .get ('crashReporterKey' )
15480 event_data .device_model = ips_file .content .get ('modelCode' )
15581 event_data .exception_type = ips_file .content .get (
15682 'exception' , {}).get ('type' )
0 commit comments