# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# 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 FileFragments
import urlparse

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

# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# @brief decode CDownloadSource structure
# @see DownloadSource.cpp - CDownloadSource::Serialize
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
def decode (decoder, version):
  data = dataholder ()
  data.url = None
  data.guid = None
  data.ip = None
  data.server_ip = None
  data.b_hash_bth = None
  data.b_hash_md5 = None
  data.nick = None
  data.country_code = None
  data.country_name = None
  data.b_meta_ignore = None
  data.b_client_extended = None
  data.fragments = []

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # version >= 21
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  if version >= 21:
    data.url = decoder.get_string ()
    data.protocol_id = decoder.get_int ()

    b_has_guid = decoder.get_dword ()
    if b_has_guid:
      data.guid = decoder.get_guid ()

    data.port = decoder.get_word ()
    if data.port:
      data.ip = decoder.get_ipv4 ()

    data.server_port = decoder.get_word ()
    if data.server_port:
      data.server_ip = decoder.get_ipv4 ()

    data.name = decoder.get_string ()
    data.index = decoder.get_dword ()
    data.hash_auth = decoder.get_bool ()
    data.b_hash_sha1 = decoder.get_bool ()
    data.b_hash_tiger = decoder.get_bool ()
    data.b_hash_ed2k = decoder.get_bool ()

    if version >= 37:
      data.b_hash_bth = decoder.get_bool ()
      data.b_hash_md5 = decoder.get_bool ()

    data.server = decoder.get_string ()

    if version >= 24:
      data.nick = decoder.get_string ()

    if version >= 36:
      data.country_code = decoder.get_string ()

    if version >= 38:
      data.country_name = decoder.get_string ()

    data.speed = decoder.get_dword ()
    data.b_push_only = decoder.get_bool ()
    data.b_close_conn = decoder.get_bool ()
    data.b_read_content = decoder.get_bool ()
    data.last_seen_time = decoder.get_nt_time ()

    data.fragments = FileFragments.decode2 (decoder, version)

    if version >= 39:
      data.b_client_extended = decoder.get_bool ()

    if version >= 42:
      data.b_meta_ignore = decoder.get_bool ()

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # version < 21
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  else:
    data.ip = decoder.get_ipv4 ()
    data.port = decoder.get_word ()
    data.speed = decoder.get_dword ()
    data.index = decoder.get_dword ()
    data.name = decoder.get_string ()

    if version >= 4:
      data.url = data.get_string ()

    data.b_hash_sha1 = data.get_bool ()

    if version >= 13:
      data.b_hash_tiger = data.get_bool ()
      data.b_hash_ed2k = data.get_bool ()

    if version >= 10:
      data.b_hash_auth = data.get_bool ()

    if version == 8:
      data.server = data.get_data (4)

    elif version >= 9:
      data.server = data.get_string ()

    data.b_push_only = data.get_bool ()
    data.b_read_content = data.get_bool ()

    if version >= 7:
      data.b_close_conn = data.get_bool ()

    if version >= 12:
      data.last_seen_time = data.get_nt_time ()

    decoder.skip (16)
    data.guid = data.get_guid ()

    data.fragments = FileFragments.decode2 (decoder, version)

  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  # If data.ip is empty, try to get IP from ED2KFTP URL
  # @see DownloadWithSources.cpp - CDownloadWithSources::Serialize
  # =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  if not data.ip and data.url and data.url.startswith ('ed2kftp://'):
    url_data = urlparse.urlparse (data.url)
    data.ip = url_data.hostname

  return data
