Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions plaso/data/formatters/ios.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,23 @@ short_source: 'HISTORY'
source: 'iOS data usage database'
---
type: 'conditional'
data_type: 'ios:discord:message'
message:
- 'User Id: {user_identifier}'
- 'Username: {username}'
- 'Message: {content}'
- 'Attachment Name: {attachment_name}'
- 'Attachment Size: {attachment_size}'
- 'Attachment type: {attachment_type}'
- 'Attachment URL: {attachment_proxy_url}'
- 'Channel Id: {channel_identifier}'
short_message:
- 'Username: {username}'
- 'Message: {content}'
short_source: 'Discord iOS'
source: 'Discord iOS Messages'
---
type: 'conditional'
data_type: 'ios:kik:messaging'
enumeration_helpers:
- input_attribute: 'message_status'
Expand Down Expand Up @@ -94,6 +111,22 @@ short_source: 'Kik iOS'
source: 'Kik iOS messages'
---
type: 'conditional'
data_type: 'ios:instagram:thread'
message:
- 'Sender ID: {sender_pk}'
- 'Username: {username}'
- 'Message: {message}'
- 'Video Chat ID: {video_chat_call_id}'
- 'Video Chat Title: {video_chat_title}'
- 'Shared Media ID: {shared_media_id}'
- 'Shared Media URL: {shared_media_url}'
short_message:
- 'Username: {username}'
- 'Message: {message}'
short_source: 'Instagram iOS'
source: 'Instagram iOS threads'
---
type: 'conditional'
data_type: 'ios:lockdownd_log:entry'
message:
- 'Process identifer: {process_identifier}'
Expand Down
12 changes: 12 additions & 0 deletions plaso/data/timeliner.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -517,12 +517,24 @@ attribute_mappings:
description: 'Start Time'
place_holder_event: true
---
data_type: 'ios:discord:message'
attribute_mappings:
- name: 'sent_time'
description: 'Sent Time'
place_holder_event: true
---
data_type: 'ios:kik:messaging'
attribute_mappings:
- name: 'received_time'
description: 'Received Time'
place_holder_event: true
---
data_type: 'ios:instagram:thread'
attribute_mappings:
- name: 'sent_time'
description: 'Sent Time'
place_holder_event: true
---
data_type: 'ios:lockdownd_log:entry'
attribute_mappings:
- name: 'written_time'
Expand Down
1 change: 1 addition & 0 deletions plaso/parsers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from plaso.parsers import firefox_cache
from plaso.parsers import fish_history
from plaso.parsers import fseventsd
from plaso.parsers import ios_discord
from plaso.parsers import java_idx
from plaso.parsers import jsonl_parser
from plaso.parsers import locate
Expand Down
111 changes: 111 additions & 0 deletions plaso/parsers/ios_discord.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# -*- coding: utf-8 -*-
"""Parser for iOS Discord message."""

import json

from dfdatetime import time_elements as dfdatetime_time_elements
from plaso.containers import events
from plaso.lib import errors
from plaso.parsers import interface
from plaso.parsers import manager


class IOSDiscordMessageEventData(events.EventData):
"""iOS discord message event data.

Attributes:
attachment_name (str): The attachment filename.
attachment_size (int): The attachment size.
attachment_type (str): The attachment type.
attachment_proxy_urls (str): The attachment proxy URL.
channel_identifier (str): ID of the user channel.
content (str): Message content.
edited_timestamp (str): Message edit time.
sent_time (dfdatetime.DateTimeValues): Message timestamp.
user_identifier (str): ID of the message author.
username (str): The username of the message sender.
"""

DATA_TYPE = 'ios:discord:message'

def __init__(self):
"""Initializes event data."""
super(IOSDiscordMessageEventData, self).__init__(data_type=self.DATA_TYPE)
self.attachment_name = None
self.attachment_proxy_url = None
self.attachment_size = None
self.attachment_type = None
self.channel_identifier = None
self.content = None
self.sent_time = None
self.user_identifier = None
self.username = None


class IOSDiscordParser(interface.FileObjectParser):
"""Parses iOS discord message log files."""

NAME = 'discord_ios'
DATA_FORMAT = 'iOS discord message'
_ENCODING = 'utf-8'
_MAXIMUM_FILE_SIZE = 16 * 1024 * 1024

def ParseFileObject(self, parser_mediator, file_object):
"""Parses a iOS discord message log file."""
file_content = file_object.read()

try:
file_content = file_content.decode(self._ENCODING)
json_data = json.loads(file_content)
except (UnicodeDecodeError, json.JSONDecodeError) as e:
raise errors.WrongParser(f'Failed to parse file as JSON: {e}')

if not isinstance(json_data, list):
raise errors.WrongParser(
'Discord log file does not contain a valid message list.')

for message in json_data:
date_time = None
timestamp = message.get('timestamp')
if timestamp:
try:
date_time = dfdatetime_time_elements.TimeElementsInMicroseconds()
date_time.CopyFromStringISO8601(timestamp)
except ValueError as exception:
parser_mediator.ProduceExtractionWarning(
'Unable to parse time string: {0:s} with error: {1!s}'.format(
timestamp, exception))
date_time = None

attachments_row = message.get('attachments', [])
if attachments_row:
att_filename = attachments_row[0].get('filename') or None
att_size = attachments_row[0].get('size') or None
att_type = attachments_row[0].get('content_type') or None
att_proxy_url = attachments_row[0].get('proxy_url') or None
else:
att_filename = None
att_size = None
att_type = None
att_proxy_url = None

channel_identifier = message.get('channel_id') or None
content = message.get('content') or None
user_identifier = message.get('author', {}).get('id') or None
username = message.get('author', {}).get('username') or None

event_data = IOSDiscordMessageEventData()
event_data.attachment_name = att_filename
event_data.attachment_proxy_url = att_proxy_url
event_data.attachment_size = att_size
event_data.attachment_type = att_type
event_data.channel_identifier = channel_identifier
event_data.content = content
event_data.sent_time = date_time
event_data.user_identifier = user_identifier
event_data.username = username

parser_mediator.ProduceEventData(event_data)


manager.ParsersManager.RegisterParser(IOSDiscordParser)
1 change: 1 addition & 0 deletions plaso/parsers/sqlite_plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
from plaso.parsers.sqlite_plugins import gdrive
from plaso.parsers.sqlite_plugins import imessage
from plaso.parsers.sqlite_plugins import ios_datausage
from plaso.parsers.sqlite_plugins import ios_instagram
from plaso.parsers.sqlite_plugins import ios_kik
from plaso.parsers.sqlite_plugins import ios_netusage
from plaso.parsers.sqlite_plugins import ios_powerlog
Expand Down
Loading