# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# Mobius Forensic Toolkit
# Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020 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 CXMLElement
import CDownloadSource
import CFragmentedFile
import CDownloadBase
import CBTInfo
import mobius

DOWNLOAD_SER_VERSION = 42	# Shareaza 2.7.10.2

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief Generic data holder
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
class dataholder (object):
  pass

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownload structure
# @see Download.cpp - CDownload::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode (decoder):

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # check file signature
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  signature = decoder.get_data (3)

  if signature != 'SDL':
    return None

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # decode data
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  version = decoder.get_dword ()

  if version > DOWNLOAD_SER_VERSION:
    mobius.core.log ("p2p.shareaza.CDownload.py: Version > %d" % DOWNLOAD_SER_VERSION)

  data = decode_CDownloadWithExtras (decoder, version)
  data.signature = signature
  data.b_expanded = decoder.get_bool ()
  data.b_paused = decoder.get_bool ()
  data.b_boosted = decoder.get_bool ()
  data.b_shared = False

  # @see Download.cpp - CDownload::IsShared
  if version >= 14:
    data.b_shared = decoder.get_bool () or bool (data.hash_sha1) or bool (data.hash_ed2k) or bool (data.hash_tiger)

  if version >= 26:
    data.ser_id = decoder.get_dword ()

  if version == 32:
    data.search_keyword = decoder.get_string ()

  # recalculate size
  data.size = max (data.size, data.estimated_size)

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownloadWithExtras structure
# @see DownloadWithExtras.cpp - CDownloadWithExtras::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode_CDownloadWithExtras (decoder, version):
  data = decode_CDownloadWithTiger (decoder, version)

  # CDownloadWithTiger code not fully implemented. So return from here
  return data

  data.previews = []
  data.reviews = []

  count = decoder.get_count ()

  for i in xrange (count):
    preview = decoder.get_string ()
    data.previews.append (preview)

  if version >= 32:
    count = decoder.get_count ()

    for i in xrange (count):
      review = decode_CDownloadReview (decoder, version)
      data.reviews.append (review)

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownloadWithTiger structure (IMPLEMENT)
# @see DownloadWithTiger.cpp - CDownloadWithTiger::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode_CDownloadWithTiger (decoder, version):
  data = decode_CDownloadWithTorrent (decoder, version)

  # @todo HashDatabase.cpp - CHashDatabase::Serialize
  height = decoder.get_dword ()

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownloadWithTorrent structure (IMPLEMENT)
# @see DownloadWithTorrent.cpp - CDownloadWithTorrent::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode_CDownloadWithTorrent (decoder, version):
  data = decode_CDownloadWithFile (decoder, version)
  data.btinfo = CBTInfo.decode (decoder)

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownloadWithFile structure
# @see DownloadWithFile.cpp - CDownloadWithFile::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode_CDownloadWithFile (decoder, version):
  data = decode_CDownloadWithSources (decoder, version)
  data.local_name = None
  data.path = None

  if version < 28:
    data.local_name = decoder.get_string ()

  if version < 25 or decoder.get_count ():
    f = CFragmentedFile.decode (decoder, version)
    if f:
      data.path = f.path
      data.bytes_to_download = f.bytes_to_download
      data.estimated_size = f.estimated_size

  return data

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownloadWithSources structure
# @see DownloadWithSources.cpp - CDownloadWithSources::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode_CDownloadWithSources (decoder, version):
  data = CDownloadBase.decode (decoder, version)
  data.sources = []
  data.pxml = None

  count = decoder.get_count ()

  for i in xrange (count):
    source = CDownloadSource.decode (decoder, version)
    data.sources.append (source)

  count = decoder.get_count ()
  if count:
    data.pxml = CXMLElement.decode (decoder)

  return data
