# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022 Eduardo Aguiar
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
import pymobius
import pymobius.app.chromium
import pymobius.app.gecko
import pymobius.app.skype

ATTR_NAME = 'data.files_received'

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Model class
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class model (object):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Initialize object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __init__ (self, item):
    self.__item = item

    if item.has_attribute (ATTR_NAME):
      self.__entries = item.get_attribute (ATTR_NAME)
      self.__entries_loaded = True

    else:
      self.__entries = []
      self.__entries_loaded = False

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get data from model
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get (self):
    if not self.__entries_loaded:
      self.__retrieve_entries ()
      self.__entries_loaded = True
      self.__item.set_attribute (ATTR_NAME, self.__entries)

    return self.__entries

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get data from model
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def refresh (self):
    self.__item.remove_attribute (ATTR_NAME)
    self.__entries = []
    self.__entries_loaded = False

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Retrieve data
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __retrieve_entries (self):
    self.__retrieve_chromium ()
    self.__retrieve_gecko ()
    self.__retrieve_skype ()

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Retrieve data from Chromium base browsers
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __retrieve_chromium (self):
    DOWNLOAD_STATE = { 0 : 'In progress', 1 : 'Complete', 2 : 'Cancelled', 3 : 'Interrupted'}

    model = pymobius.app.chromium.model (self.__item)

    for profile in model.get_profiles ():
      for d in profile.get_downloads ():
        entry = pymobius.Data ()
        entry.username = profile.username
        entry.start_time = d.start_time
        entry.end_time = d.end_time
        entry.filename = d.name
        entry.path = d.target
        entry.app_id = profile.app_id
        entry.app_name = profile.app_name
        entry.item = self.__item.name

        entry.metadata = []
        entry.metadata.append (('URL', d.source))
        entry.metadata.append (('Size', d.size))
        entry.metadata.append (('Bytes downloaded', d.bytes_downloaded))
        entry.metadata.append (('Download state', DOWNLOAD_STATE.get (d.state, 'Unknown (%d)' % d.state)))
        entry.metadata.append (('Page referrer', d.referrer))

        self.__entries.append (entry)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Retrieve data from Gecko based browsers
  # @see http://doxygen.db48x.net/mozilla/html/interfacensIDownloadManager.html
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __retrieve_gecko (self):
    DOWNLOAD_STATE = { 0 : '', 1 : 'Finished', 2 : 'Failed', 3 : 'Cancelled', 4 : 'Paused', 5 : 'Queued', 6 : 'Blocked Parental', 7 : 'Scanning', 8 : 'Virus Detected', 9 : 'Blocked Policy'}

    model = pymobius.app.gecko.model (self.__item)

    for profile in model.get_profiles ():
      for d in profile.get_downloads ():
        entry = pymobius.Data ()
        entry.username = profile.username
        entry.start_time = d.start_time
        entry.end_time = d.end_time
        entry.filename = d.name
        entry.path = d.target
        entry.app_id = profile.app_id
        entry.app_name = profile.app_name
        entry.item = self.__item.name

        entry.metadata = []
        entry.metadata.append (('URL', d.source))
        entry.metadata.append (('Size', d.size))
        entry.metadata.append (('Bytes downloaded', d.bytes_downloaded))
        entry.metadata.append (('Download state', DOWNLOAD_STATE.get (d.state, 'Unknown (%d)' % d.state)))
        entry.metadata.append (('Page referrer', d.referrer))

        self.__entries.append (entry)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Retrieve data from Skype
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __retrieve_skype (self):
    DOWNLOAD_STATE = { 0 : 'Not initiated', 7 : 'Cancelled', 8 : 'Completed', 9 : 'Error' }
    model = pymobius.app.skype.model (self.__item)

    for profile in model.get_profiles ():
      for ft in profile.get_file_transfers ():
        if ft.type == 1:
          entry = pymobius.Data ()
          entry.username = profile.username
          entry.start_time = ft.start_time
          entry.end_time = ft.finish_time
          entry.filename = ft.filename
          entry.path = ft.path
          entry.app_id = 'skype'
          entry.app_name = 'Skype'
          entry.item = self.__item.name

          entry.metadata = []
          entry.metadata.append (('Size', ft.size))
          entry.metadata.append (('Bytes received', ft.bytes_transferred))
          entry.metadata.append (('Transfer state', DOWNLOAD_STATE.get (ft.status, 'Unknown (%d)' % ft.status)))

          sender = ft.from_skype_account
          if ft.from_skype_name:
            sender += ' (%s)' % ft.from_skype_name

          receiver = ft.to_skype_account
          if ft.to_skype_name:
            receiver += ' (%s)' % ft.to_skype_name

          entry.metadata.append (('Sender account', sender))
          entry.metadata.append (('Receiver account', receiver))

          self.__entries.append (entry)
