# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# 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.path
import pymobius.app.gecko.decoder_cookies
import pymobius.app.gecko.decoder_downloads
import pymobius.app.gecko.decoder_formhistory
import pymobius.app.gecko.decoder_places
import pymobius
#import beta.util

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

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Initialize object
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __init__ (self, folder):
    self.app_id = 'geckofx'
    self.app_name = 'GeckoFX'
    self.creation_time = folder.creation_time
    self.__cookies_loaded = False
    self.__downloads_loaded = False
    self.__form_history_loaded = False
    self.__history_loaded = False

    self.__cookies = []
    self.__downloads = []
    self.__form_history = []
    self.__history = []
    self.__searches = []

    # beta.util.dirtree (folder)	# development only

    self.__roaming_folder = folder
    self.path = folder.path.replace ('/', '\\')
    
    if folder.name.lower ().endswith ('.default'):
      self.name = folder.name[:-8]

    else:
      self.name = folder.name

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get cookies from cookies.sqlite
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_cookies (self):

    if not self.__cookies_loaded:
      f = self.__roaming_folder.get_child_by_path ('cookies.sqlite')

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

      self.__cookies_loaded = True

    return self.__cookies

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get download history from downloads.sqlite
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_downloads (self):

    if not self.__downloads_loaded:
      f = self.__roaming_folder.get_child_by_path ('downloads.sqlite')

      if f and not f.is_reallocated:
        data = pymobius.app.gecko.decoder_downloads.decode (f)
        self.__downloads = data.downloads

      self.__downloads_loaded = True

    return self.__downloads

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get form history
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_form_history (self):

    if not self.__form_history_loaded:
      self.__load_form_history ()

    return self.__form_history

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get search history
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_searches (self):

    if not self.__form_history_loaded:
      self.__load_form_history ()

    return self.__searches

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Get history entries from places.sqlite
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def get_history (self):

    if not self.__history_loaded:
      f = self.__roaming_folder.get_child_by_path ('places.sqlite')

      if f and not f.is_reallocated:
        data = pymobius.app.gecko.decoder_places.decode (f)
        self.__history = data.history
        
        for h in self.__history:
          h.url = h.url.encode ('ascii')
          h.profile_path = self.path
          h.profile_name = self.name
          h.username = self.username

      self.__history_loaded = True

    return self.__history

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # @brief Load form history from formhistory.sqlite
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  def __load_form_history (self):
    f = self.__roaming_folder.get_child_by_path ('formhistory.sqlite')

    if f and not f.is_reallocated:
      self.__form_history = []
      self.__searches = []

      for entry in pymobius.app.gecko.decoder_formhistory.decode (f):

        if entry.fieldname == 'searchbar-history':
          search = pymobius.Data ()
          search.id = entry.id
          search.text = entry.value
          search.timestamp = entry.first_used_time
          self.__searches.append (search)
          
          if entry.last_used_time and entry.first_used_time != entry.last_used_time:
            search = pymobius.Data ()
            search.id = entry.id
            search.text = entry.value
            search.timestamp = entry.last_used_time
            self.__searches.append (search)

        else:
          self.__form_history.append (entry)

    self.__form_history_loaded = True

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

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

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

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