# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019 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 os
import os.path
import pymobius.app.chromium
import pymobius.app.chromium.decoder_cookies
import pymobius.app.chromium.decoder_history
import pymobius.app.chromium.decoder_login_data
import pymobius.app.chromium.decoder_web_data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Known files list
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
KFF_FILES = [
  'Cookies',
  'History',
  'Login Data',
  'Web Data'
]

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Opera Profile class
# @author Eduardo Aguiar
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class Profile (object):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Initialize object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __init__ (self, folder):
    self.app_id = 'opera'
    self.app_name = 'Opera'
    self.creation_time = folder.creation_time
    self.__history_loaded = False
    self.__web_data_loaded = False
    self.__cookies_loaded = False
    self.__login_data_loaded = False
    self.__history = []
    self.__cookies = []
    self.__downloads = []
    self.__form_history = []
    self.__stored_passwords = []

    self.__local_folder = folder
    self.path = folder.path.replace ('/', '\\')

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get cookies from Cookies file
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_cookies (self):

    if not self.__cookies_loaded:
      f = self.__local_folder.get_child_by_path ('Cookies')

      if f and not f.is_reallocated:      
        data = pymobius.app.chromium.decoder_cookies.decode (f)
        self.__cookies = data.cookies

      self.__cookies_loaded = True

    return self.__cookies

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get download history from History file
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_downloads (self):
    if not self.__history_loaded:
      self.__load_history ()

    return self.__downloads

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get form history from Web Data file
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_form_history (self):

    if not self.__web_data_loaded:
      self.__web_data_loaded = True

      f, path = self.__retrieve_file ('Web Data')
      if path:
        data = pymobius.app.chromium.decoder_web_data.decode (path)
        self.__form_history = data.form_history
        os.remove (path)

    return self.__form_history

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get history entries from History file
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_history (self):
    if not self.__history_loaded:
      self.__load_history ()

    return self.__history

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get stored passwords
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_stored_passwords (self):

    if not self.__login_data_loaded:
      self.__login_data_loaded = True
      
      f, path = self.__retrieve_file ('Login Data')
      if path:
        data = pymobius.app.chromium.decoder_login_data.decode (path)
        self.__stored_passwords = data.stored_passwords
        os.remove (path)

    return self.__stored_passwords

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get known files list
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_known_files (self):

    for kff_file in KFF_FILES:
      f = self.__local_folder.get_child_by_name (kff_file, False)

      if f and not f.is_reallocated:
        yield f

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Load data from History file
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __load_history (self):

    # retrieve data
    f, path = self.__retrieve_file ('History')

    if path:
      data = pymobius.app.chromium.decoder_history.decode (path)
      self.__history += data.history
      self.__downloads += data.downloads

      os.remove (path)

    # set history loaded
    self.__history_loaded = True

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Retrieve file into temp directory
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __retrieve_file (self, rpath):
    f = self.__local_folder.get_child_by_path (rpath)

    return f, pymobius.app.chromium.retrieve_db_file (f)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get any file (development only)
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_file (self, rpath):

    # try to get file
    f = self.__local_folder.get_child_by_path (rpath, False)
    if not f:
      return

    reader = f.new_reader ()
    if not reader:
      return

    # create temporary .sqlite local file
    fp = open (os.path.basename (rpath), 'w')
    fp.write (reader.read ())
    fp.close ()
