# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# 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 CSearchWnd
import CXMLElement
import mobius
import pymobius.p2p
import pymobius.p2p.search
import pymobius.p2p.remote_file
import base64

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief retrieve data from Searches.dat
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def retrieve (item, model, f, username):

  # check file
  if not f:
    return

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

  # decode file
  decoder = mobius.decoder.mfc (reader)
  count = decoder.get_count ()
  csearch_wnd_list = []

  while count == 1:
    csearch_wnd = CSearchWnd.decode (decoder)
    csearch_wnd_list.append (csearch_wnd)
    count = decoder.get_count ()

  # process data
  d_search = {}
  searches = []

  for csearch_wnd in csearch_wnd_list:

    # generate search history
    for s in csearch_wnd.searches:
      qs = s.qs
      search_id = qs.guid

      search = pymobius.p2p.search.search ()
      search.app_id = 'shareaza'
      search.app = 'Shareaza'
      search.username = username
      search.text = qs.search_string
      search.timestamp = None
      search.first_hit_time = None
      search.last_hit_time = None
      search.pxml = qs.pxml

      search.add_metadata ('Application', 'Shareaza')
      search.add_metadata ('User name', username)
      search.add_metadata ('Search ID', qs.guid)
      search.add_metadata ('Search Term', qs.search_string)
      search.add_metadata ('Min. size', qs.min_size)
      search.add_metadata ('Max. size', qs.max_size)

      searches.append (search)
      d_search[search_id] = search

    # generate remote files list
    for match_file in csearch_wnd.match_list.match_files:
      for q in match_file.query_hits:
        search = d_search.get (q.search_id)
        if not search:
          continue

        rf = new_remote_file (match_file, q, search)
        rf.username = username
        model.remote_files.append (rf)

        if not search.timestamp or search.timestamp > rf.timestamp:
          search.timestamp = rf.timestamp
          search.first_hit_time = rf.timestamp

        if not search.last_hit_time or search.last_hit_time < rf.timestamp:
          search.last_hit_time = rf.timestamp

        search.add_file (rf)

  # normalize data
  for search in searches:
    search.add_metadata ('Hits', search.get_file_count ())

    if search.first_hit_time:
      search.add_metadata ('First Hit Date/Time', search.first_hit_time)
      
    if search.last_hit_time:
      search.add_metadata ('Last Hit Date/Time', search.last_hit_time)

    for name, value in CXMLElement.get_metadata_from_pxml (search.pxml):
      search.add_metadata (name, value)

    model.searches.append (search)

  # set file handled
  pymobius.p2p.set_handled (item, f)

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Create remote file
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def new_remote_file (match_file, q, search):
  f = pymobius.p2p.remote_file.remote_file ()
  f.app_id = 'shareaza'
  f.app = 'Shareaza'
  f.name = q.name
  f.size = match_file.size
  f.timestamp = match_file.last_seen_time
  f.url = q.url

  if match_file.preview:
    f.preview_data = base64.b64encode (match_file.preview)
  else:
    f.preview_data = None

  # peer
  f.peer.ip = q.ip
  f.peer.port = q.port
  f.peer.nickname = q.nick
  f.peer.application = q.peer_app

  # hashes
  f.set_hash ('sha1', match_file.hash_sha1)
  f.set_hash ('tiger', match_file.hash_tiger)
  f.set_hash ('ed2k', match_file.hash_ed2k)
  f.set_hash ('bth', match_file.hash_bth)
  f.set_hash ('md5', match_file.hash_md5)

  # metadata
  f.add_metadata ('Search Term', search.text)
  f.add_metadata ('Comments', q.comments)
  f.add_metadata ('Client ID', q.client_id)
  
  for name, value in CXMLElement.get_metadata_from_pxml (q.pxml):
    f.add_metadata (name, value)

  return f
