// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Mobius Forensic Toolkit
// Copyright (C) 2008,2009,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022,2023,2024,2025 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/>.
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// All Date/Times are stored in Coordinated Universal Time (UTC).
// !\see https://msdn.microsoft.com/pt-br/library/windows/desktop/ms724397(v=vs.85).aspx
//
// References:
//   . Shareaza 2.7.10.2 source code
//
// Shareaza main files:
//   . Searches.dat - Stores search history and search results
//   . Library1.dat and Library2.dat - Stores configuration for local folders and files
//   . *.sd files - Download control files (one per downloading file)
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

#include "evidence_loader_impl.h"
//#include "file_profile_xml.h"
#include <mobius/io/walker.h>
#include <mobius/core/log.h>
#include <mobius/datasource/datasource_vfs.h>
#include <mobius/exception.inc>
#include <mobius/io/folder.h>
#include <mobius/io/path.h>
#include <mobius/model/evidence.h>
#include <mobius/os/win/registry/hive_file.h>
#include <mobius/os/win/registry/hive_data.h>
#include <mobius/pod/map.h>
#include <mobius/string_functions.h>
#include <algorithm>
#include <stdexcept>

#include <iostream>

namespace
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
// Constants
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static const std::string APP_ID = "shareaza";
static const std::string APP_NAME = "Shareaza";
static const std::string ANT_ID = "evidence.app-shareaza";
static const std::string ANT_NAME = APP_NAME;
static const std::string ANT_VERSION = "1.0";

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Update metadata map, preferring non null values
//! \param metadata Metadata map
//! \param other Other metadata map
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
static void
update_metadata (mobius::pod::map& metadata, const mobius::pod::map& other)
{
  for (const auto& [k, v] : other)
    {
      auto old_v = metadata.get (k);

      if (!metadata.contains (k) || (old_v.is_null () && !v.is_null ()))
        metadata.set (k, v);
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Get vector of hashes for a given file
//! \param f File structure
//! \return Vector
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
/*std::vector <mobius::pod::data>
get_file_hashes (const mobius::extension::app::shareaza::file& f)
{
  std::vector <mobius::pod::data> hashes;

  if (!f.hash_sha1.empty ())
    hashes.push_back ({"sha1", f.hash_sha1});

  return hashes;
}*/

} // namespace

namespace mobius::extension::app::shareaza
{
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Constructor
//! \param item Item object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
evidence_loader_impl::evidence_loader_impl (const mobius::model::item& item, scan_type type)
  : item_ (item),
    scan_type_ (type)
{
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Scan item files for evidences
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::run ()
{
  mobius::core::log log (__FILE__, __FUNCTION__);
  log.info (__LINE__, "Evidence loader <app-" + APP_ID + "> started");
  log.info (__LINE__, "Item UID: " + std::to_string (item_.get_uid ()));
  log.info (__LINE__, "Scan mode: " + std::to_string (static_cast <int> (scan_type_)));

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Check if loader has already run for item
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  if (item_.has_ant (ANT_ID))
    {
      log.info (__LINE__, "Evidence loader <app-" + APP_ID + "> has already run");
      return ;
    }

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Check datasource
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  auto datasource = item_.get_datasource ();

  if (!datasource)
    throw std::runtime_error ("item has no datasource");

  if (datasource.get_type () != "vfs")
    throw std::runtime_error ("datasource type is not VFS");

  if (!datasource.is_available ())
    throw std::runtime_error ("datasource is not available");

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Scan item files, according to scan_type
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  switch (scan_type_)
    {
      case scan_type::canonical_folders:
        _scan_canonical_folders ();
        break;

      case scan_type::all_folders:
        //_scan_all_folders ();
        break;

      default:
        log.warning (__LINE__, "invalid scan type: " + std::to_string (static_cast <int> (scan_type_)));
        return;
    }

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Save evidences
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  _save_evidences ();
  log.info (__LINE__, "Evidence loader <app-" + APP_ID + "> ended");
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Scan canonical folders
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_scan_canonical_folders ()
{
  auto vfs_datasource = mobius::datasource::datasource_vfs (item_.get_datasource ());
  auto vfs = vfs_datasource.get_vfs ();

  for (const auto& entry : vfs.get_root_entries ())
    {
      if (entry.is_folder ())
        _scan_canonical_root_folder (entry.get_folder ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Scan root folder for evidences
//! \param folder Root folder
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_scan_canonical_root_folder (const mobius::io::folder& folder)
{
  auto w = mobius::io::walker (folder);

  for (const auto& f : w.get_folders_by_pattern ("users/*"))
    _scan_canonical_user_folder (f);
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Scan user folder for evidences
//! \param folder User folder
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_scan_canonical_user_folder (const mobius::io::folder& folder)
{
  username_ = folder.get_name ();
  account_ = {};

  auto w = mobius::io::walker (folder);

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Scan evidence files
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  for (const auto& f : w.get_files_by_name ("ntuser.dat"))
    _decode_ntuser_dat_file (f);

  for (const auto& f : w.get_folders_by_path ("appdata/roaming/shareaza/data"))
    _scan_canonical_shareaza_data_folder (f);

  for (const auto& f : w.get_files_by_pattern ("appdata/local/shareaza/incomplete/*.sd"))
    _decode_sd_file (f);

  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  // Copy consolidated files to the list of all files found
  // If file is a torrent file, copy its own component files instead
  // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
  /*for (const auto& [hash_sha1, af] : account_files_)
    {
      std::ignore = hash_sha1;

      if (af.torrent_files.size () == 0)
        files_.push_back (af);

      else
        {
          for (const auto& tf : af.torrent_files)
            {
              file f = af;

              f.size = tf.size;
              f.filename = tf.name;
              f.path = tf.path;
              f.hash_sha1.clear ();

              f.metadata = af.metadata.clone ();
              f.metadata.set ("torrent_file_idx", tf.idx);
              f.metadata.set ("torrent_last_modification_time", tf.last_modification_time);

              files_.push_back (f);
            }
        }
    }

  account_files_.clear ();*/

}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Scan AppData/Roaming/Shareaza/Data folder for evidences
//! \param folder Data folder
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_scan_canonical_shareaza_data_folder (const mobius::io::folder& folder)
{
  mobius::io::walker w (folder);

  for (const auto& f : w.get_files ())
    {
      const std::string lname = mobius::string::tolower (f.get_name ());

      if (lname == "library1.dat")
        _decode_library_dat_file (f);

      else if (lname == "library2.dat")
        _decode_library_dat_file (f);

      else if (lname == "searches.dat")
        _decode_searches_dat_file (f);

      else if (lname == "profile.xml")
        _decode_profile_xml_file (f);
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode LibraryN.dat file
//! \param f File object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_decode_library_dat_file (const mobius::io::file& f)
{
  mobius::core::log log (__FILE__, __FUNCTION__);

std::cerr << "Library file: " << f.get_path () << std::endl;

  try
    {
/*      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Decode file
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      file_shareh shareh (f.new_reader ());

      if (!shareh)
        {
          log.info (__LINE__, "File is not an instance of ShareH.dat. Path: " + f.get_path ());
          return;
        }

      log.info (__LINE__, "ShareH.dat file decoded. Path: " + f.get_path ());

      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Get entries
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      bool is_deleted = f.is_deleted ();

      for (const auto& entry : shareh)
        {
          auto [iter, success] = account_files_.try_emplace (entry.hash_sha1, file {});
          std::ignore = success;
          auto& fobj = iter->second;

          if (!fobj.shareh_f || (fobj.shareh_f.is_deleted () && !is_deleted))
            {
              fobj.hash_sha1 = entry.hash_sha1;
              fobj.account_guid = account_.guid;
              fobj.username = username_;
              fobj.download_completed_time = entry.download_completed_time;
              fobj.shareh_idx = entry.idx;
              fobj.shareh_f = f;

              fobj.flag_shared = entry.is_shared;
              fobj.flag_completed = true;  // ShareH entries are always completed
              fobj.flag_corrupted = entry.is_corrupted;

              if (fobj.download_completed_time)
                fobj.flag_downloaded = true;

              fobj.metadata.set ("title", entry.title);
              fobj.metadata.set ("artist", entry.artist);
              fobj.metadata.set ("album", entry.album);
              fobj.metadata.set ("category", entry.category);
              fobj.metadata.set ("year", entry.year);
              fobj.metadata.set ("language", entry.language);
              fobj.metadata.set ("url", entry.url);
              fobj.metadata.set ("comment", entry.comment);
              fobj.metadata.set ("download_completed_time", entry.download_completed_time);
            }
        }*/
    }
  catch (const std::exception& e)
    {
      log.warning (__LINE__, e.what ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode Searches.dat file
//! \param f File object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_decode_searches_dat_file (const mobius::io::file& f)
{
  mobius::core::log log (__FILE__, __FUNCTION__);

std::cerr << "Searches file: " << f.get_path () << std::endl;

  try
    {
/*      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Decode file
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      file_shareh shareh (f.new_reader ());

      if (!shareh)
        {
          log.info (__LINE__, "File is not an instance of ShareH.dat. Path: " + f.get_path ());
          return;
        }

      log.info (__LINE__, "ShareH.dat file decoded. Path: " + f.get_path ());

      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Get entries
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      bool is_deleted = f.is_deleted ();

      for (const auto& entry : shareh)
        {
          auto [iter, success] = account_files_.try_emplace (entry.hash_sha1, file {});
          std::ignore = success;
          auto& fobj = iter->second;

          if (!fobj.shareh_f || (fobj.shareh_f.is_deleted () && !is_deleted))
            {
              fobj.hash_sha1 = entry.hash_sha1;
              fobj.account_guid = account_.guid;
              fobj.username = username_;
              fobj.download_completed_time = entry.download_completed_time;
              fobj.shareh_idx = entry.idx;
              fobj.shareh_f = f;

              fobj.flag_shared = entry.is_shared;
              fobj.flag_completed = true;  // ShareH entries are always completed
              fobj.flag_corrupted = entry.is_corrupted;

              if (fobj.download_completed_time)
                fobj.flag_downloaded = true;

              fobj.metadata.set ("title", entry.title);
              fobj.metadata.set ("artist", entry.artist);
              fobj.metadata.set ("album", entry.album);
              fobj.metadata.set ("category", entry.category);
              fobj.metadata.set ("year", entry.year);
              fobj.metadata.set ("language", entry.language);
              fobj.metadata.set ("url", entry.url);
              fobj.metadata.set ("comment", entry.comment);
              fobj.metadata.set ("download_completed_time", entry.download_completed_time);
            }
        }*/
    }
  catch (const std::exception& e)
    {
      log.warning (__LINE__, e.what ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode Profile.xml file
//! \param f File object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_decode_profile_xml_file (const mobius::io::file& f)
{
  mobius::core::log log (__FILE__, __FUNCTION__);

std::cerr << "Profile.xml file: " << f.get_path () << std::endl;

  try
    {
/*      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Decode file
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      file_shareh shareh (f.new_reader ());

      if (!shareh)
        {
          log.info (__LINE__, "File is not an instance of ShareH.dat. Path: " + f.get_path ());
          return;
        }

      log.info (__LINE__, "ShareH.dat file decoded. Path: " + f.get_path ());

      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Get entries
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      bool is_deleted = f.is_deleted ();

      for (const auto& entry : shareh)
        {
          auto [iter, success] = account_files_.try_emplace (entry.hash_sha1, file {});
          std::ignore = success;
          auto& fobj = iter->second;

          if (!fobj.shareh_f || (fobj.shareh_f.is_deleted () && !is_deleted))
            {
              fobj.hash_sha1 = entry.hash_sha1;
              fobj.account_guid = account_.guid;
              fobj.username = username_;
              fobj.download_completed_time = entry.download_completed_time;
              fobj.shareh_idx = entry.idx;
              fobj.shareh_f = f;

              fobj.flag_shared = entry.is_shared;
              fobj.flag_completed = true;  // ShareH entries are always completed
              fobj.flag_corrupted = entry.is_corrupted;

              if (fobj.download_completed_time)
                fobj.flag_downloaded = true;

              fobj.metadata.set ("title", entry.title);
              fobj.metadata.set ("artist", entry.artist);
              fobj.metadata.set ("album", entry.album);
              fobj.metadata.set ("category", entry.category);
              fobj.metadata.set ("year", entry.year);
              fobj.metadata.set ("language", entry.language);
              fobj.metadata.set ("url", entry.url);
              fobj.metadata.set ("comment", entry.comment);
              fobj.metadata.set ("download_completed_time", entry.download_completed_time);
            }
        }*/
    }
  catch (const std::exception& e)
    {
      log.warning (__LINE__, e.what ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode Incomplete/*.sd file
//! \param f File object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_decode_sd_file (const mobius::io::file& f)
{
  mobius::core::log log (__FILE__, __FUNCTION__);

  try
    {
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Decode file
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
std::cerr << "SD file: " << f.get_path () << std::endl;
/*
      file_pbthash pbthash (f.new_reader ());

      if (!pbthash)
        {
          log.info (__LINE__, "File is not an instance of PBTHash. Path: " + f.get_path ());
          return;
        }

      log.info (__LINE__, "PBTHash file decoded. Path: " + f.get_path ());

      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Process file
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      bool is_deleted = f.is_deleted ();

      auto hash_sha1 = pbthash.get_hash_sha1 ();
      auto [iter, success] = account_files_.try_emplace (hash_sha1, file {});
      std::ignore = success;
      auto& fobj = iter->second;

      if (!fobj.tempdl_pbthash_f || (fobj.tempdl_pbthash_f.is_deleted () && !is_deleted))
        {
          fobj.hash_sha1 = hash_sha1;
          fobj.account_guid = account_.guid;
          fobj.username = username_;
          fobj.size = pbthash.get_file_size ();
          fobj.tempdl_pbthash_f = f;

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Set path and name
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto path = pbthash.get_torrent_path ();
          if (!path.empty ())
            fobj.path = path;

          auto name = pbthash.get_torrent_name ();
          if (!name.empty ())
            fobj.filename = name;

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Test if every piece is checked
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto pieces = pbthash.get_pieces ();
          auto is_checked = std::all_of (
              pieces.begin (),
              pieces.end (),
              [](const auto& p){ return p.is_checked; }
          );

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Set flags
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          fobj.flag_downloaded = true;
          fobj.flag_completed.set_if_unknown (pbthash.is_completed ());
          fobj.flag_uploaded.set_if_unknown (pbthash.get_bytes_uploaded () > 0);
          fobj.flag_shared.set_if_unknown (pbthash.is_seeding ());
          fobj.flag_corrupted.set_if_unknown (!is_checked);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Set torrent files
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto files = pbthash.get_files ();

          std::transform (
              files.begin (),
              files.end (),
              std::back_inserter (fobj.torrent_files),
              [](const auto& tf){ return torrent_file {tf.idx, tf.size, tf.last_modification_time, tf.name, tf.path}; }
          );

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Set metadata
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          fobj.metadata.set ("torrent_url", "magnet:?xt=urn:btih:" + hash_sha1);
          fobj.metadata.set ("torrent_pieces_count", pbthash.get_pieces_count ());
          fobj.metadata.set ("torrent_piece_size", pbthash.get_piece_size ());
          fobj.metadata.set ("torrent_files_count", pbthash.get_files_count ());
          fobj.metadata.set ("torrent_bytes_downloaded", pbthash.get_bytes_downloaded ());
          fobj.metadata.set ("torrent_bytes_uploaded", pbthash.get_bytes_uploaded ());
          fobj.metadata.set ("torrent_path", pbthash.get_torrent_path ());
          fobj.metadata.set ("torrent_name", pbthash.get_torrent_name ());
          fobj.metadata.set ("torrent_download_started_time", pbthash.get_download_started_time ());
        }*/
    }
  catch (const std::exception& e)
    {
      log.warning (__LINE__, e.what ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Decode data from NTUSER.dat file
//! \param f File object
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_decode_ntuser_dat_file (const mobius::io::file& f)
{
  mobius::core::log log (__FILE__, __FUNCTION__);

  try
    {
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Create decoder
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      auto decoder = mobius::os::win::registry::hive_file (f.new_reader ());

      if (!decoder.is_instance ())
        {
          log.info (__LINE__, "File " + f.get_path () + " ignored.");
          return;
        }

      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      // Get evidences from Shareaza key
      // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
      const auto& root_key = decoder.get_root_key ();
      const auto& shareaza_key = root_key.get_key_by_path ("Software\\Shareaza\\Shareaza");

      if (shareaza_key)
        {
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Set account
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          account acc;
          acc.username = username_;
          acc.is_deleted = f.is_deleted ();
          acc.f = f;

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Load values from key
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          acc.install_path = shareaza_key.get_data_by_name ("Path").get_data_as_string ("utf-16le");
          acc.user_path = shareaza_key.get_data_by_name ("UserPath").get_data_as_string ("utf-16le");

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Load values from Downloads key
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          const auto& download_key = shareaza_key.get_key_by_name ("Downloads");

          if (download_key)
            {
              acc.collection_path = download_key.get_data_by_name ("CollectionPath").get_data_as_string ("utf-16le");
              acc.complete_path = download_key.get_data_by_name ("CompletePath").get_data_as_string ("utf-16le");
              acc.incomplete_path = download_key.get_data_by_name ("IncompletePath").get_data_as_string ("utf-16le");
              acc.torrent_path = download_key.get_data_by_name ("TorrentPath").get_data_as_string ("utf-16le");
            }

          /*if (account_.guid.empty () ||
              (account_.is_deleted && !acc.is_deleted))
            account_ = acc;*/

          accounts_.push_back (acc);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Load autofill values
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          for (const auto& value: shareaza_key.get_values_by_mask ("Search\\Search.*"))
            {
              autofill af;

              af.value = mobius::string::word (value.get_data ().get_data_as_string ("utf-16le"), 0, "\n");
              af.username = username_;
              af.id = value.get_name ().substr(7);
              af.is_deleted = acc.is_deleted;
              af.f = f;

              autofills_.push_back (af);
            }
        }
    }
  catch (const std::exception& e)
    {
      log.warning (__LINE__, e.what ());
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save evidences
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_evidences ()
{
  auto transaction = item_.new_transaction ();

  _save_accounts ();
  _save_autofills ();
  //_save_local_files ();
  //_save_p2p_remote_files ();
  //_save_received_files ();
  //_save_searched_texts ();
  //_save_sent_files ();
  //_save_shared_files ();

  item_.set_ant (ANT_ID, ANT_NAME, ANT_VERSION);
  transaction.commit ();
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save accounts
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_accounts ()
{
  for (const auto& a : accounts_)
    {
      mobius::pod::map metadata;
      metadata.set ("app_id", APP_ID);
      metadata.set ("app_name", APP_NAME);
      metadata.set ("username", a.username);
      metadata.set ("gnutella_guid", a.gnutella_guid);
      metadata.set ("bittorrent_guid", a.bittorrent_guid);

      if (!a.gnutella_guid.empty ())
        {
          auto e = item_.new_evidence ("user-account");

          e.set_attribute ("account_type", "app.shareaza");
          e.set_attribute ("id", a.gnutella_guid);
          e.set_attribute ("password", {});
          e.set_attribute ("password_found", "no");
          e.set_attribute ("is_deleted", a.is_deleted);
          e.set_attribute ("metadata", metadata.clone ());
          e.set_tag ("p2p");
          e.add_source (a.f);
        }

      if (!a.bittorrent_guid.empty ())
        {
          auto e = item_.new_evidence ("user-account");

          e.set_attribute ("account_type", "app.shareaza");
          e.set_attribute ("id", a.bittorrent_guid);
          e.set_attribute ("password", {});
          e.set_attribute ("password_found", "no");
          e.set_attribute ("is_deleted", a.is_deleted);
          e.set_attribute ("metadata", metadata.clone ());
          e.set_tag ("p2p");
          e.add_source (a.f);
        }
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save autofill entries
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_autofills ()
{
  for (const auto& a : autofills_)
    {
      mobius::pod::map metadata;
      metadata.set ("id", a.id);

      auto e = item_.new_evidence ("autofill");

      e.set_attribute ("field_name", "search");
      e.set_attribute ("value", a.value);
      e.set_attribute ("app_id", APP_ID);
      e.set_attribute ("app_name", APP_NAME);
      e.set_attribute ("username", a.username);
      e.set_attribute ("is_deleted", a.is_deleted);
      e.set_attribute ("metadata", metadata);
      e.set_tag ("p2p");
      e.add_source (a.f);
    }
}

/*
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save local files
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_local_files ()
{
  for (const auto& f : files_)
    {
      if (!f.path.empty ())
        {
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Create evidence
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto e = item_.new_evidence ("local-file");

          e.set_attribute ("username", f.username);
          e.set_attribute ("path", f.path);
          e.set_attribute ("app_id", APP_ID);
          e.set_attribute ("app_name", APP_NAME);
          e.set_attribute ("hashes", get_file_hashes (f));

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Metadata
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          mobius::pod::map metadata;

          metadata.set ("size", f.size);
          metadata.set ("flag_downloaded", to_string (f.flag_downloaded));
          metadata.set ("flag_uploaded", to_string (f.flag_uploaded));
          metadata.set ("flag_shared", to_string (f.flag_shared));
          metadata.set ("flag_corrupted", to_string (f.flag_corrupted));
          metadata.set ("flag_completed", to_string (f.flag_completed));

          if (f.shareh_idx)
            metadata.set ("shareh_idx", f.shareh_idx);

          if (f.sharel_idx)
            metadata.set ("sharel_idx", f.sharel_idx);

          if (f.torrenth_idx)
            metadata.set ("torrenth_idx", f.torrenth_idx);

          if (f.phashidx_idx)
            metadata.set ("phashidx_idx", f.phashidx_idx);

          metadata.set ("network", "Ares");
          update_metadata (metadata, f.metadata);

          e.set_attribute ("metadata", metadata);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Tags
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.set_tag ("p2p");

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Sources
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.add_source (f.shareh_f);
          e.add_source (f.sharel_f);
          e.add_source (f.phashidx_f);
          e.add_source (f.arestra_f);
          e.add_source (f.tempdl_pbthash_f);
          e.add_source (f.tempdl_phash_f);
          e.add_source (f.tempul_udpphash_f);
        }
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save received files
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_received_files ()
{
  for (const auto& f : files_)
    {
      if (f.flag_downloaded.is_yes ())
        {
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Create evidence
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto e = item_.new_evidence ("received-file");

          if (f.download_completed_time)
            e.set_attribute ("timestamp", f.download_completed_time);

          else if (f.download_started_time)
            e.set_attribute ("timestamp", f.download_started_time);

          e.set_attribute ("filename", f.filename);
          e.set_attribute ("path", f.path);
          e.set_attribute ("username", f.username);
          e.set_attribute ("app_id", APP_ID);
          e.set_attribute ("app_name", APP_NAME);
          e.set_attribute ("hashes", get_file_hashes (f));

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Metadata
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          mobius::pod::map metadata;
          metadata.set ("flag_downloaded", to_string (f.flag_downloaded));
          metadata.set ("flag_uploaded", to_string (f.flag_uploaded));
          metadata.set ("flag_shared", to_string (f.flag_shared));
          metadata.set ("flag_corrupted", to_string (f.flag_corrupted));
          metadata.set ("flag_completed", to_string (f.flag_completed));

          if (f.shareh_idx)
            metadata.set ("shareh_idx", f.shareh_idx);

          if (f.sharel_idx)
            metadata.set ("sharel_idx", f.sharel_idx);

          if (f.torrenth_idx)
            metadata.set ("torrenth_idx", f.torrenth_idx);

          if (f.phashidx_idx)
            metadata.set ("phashidx_idx", f.phashidx_idx);

          metadata.set ("network", "Ares");
          update_metadata (metadata, f.metadata);

          e.set_attribute ("metadata", metadata);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Tags
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.set_tag ("p2p");

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Sources
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.add_source (f.shareh_f);
          e.add_source (f.sharel_f);
          e.add_source (f.torrenth_f);
          e.add_source (f.phashidx_f);
          e.add_source (f.arestra_f);
          e.add_source (f.tempdl_pbthash_f);
          e.add_source (f.tempdl_phash_f);
          e.add_source (f.tempul_udpphash_f);
        }
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save remote files
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_p2p_remote_files ()
{
  for (const auto& f : files_)
    {
      for (const auto& rs : f.remote_sources)
        {
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Create evidence
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto e = item_.new_evidence ("p2p-remote-file");
          e.set_attribute ("timestamp", rs.timestamp);
          e.set_attribute ("ip", rs.ip);
          e.set_attribute ("port", rs.port);
          e.set_attribute ("filename", f.filename);
          e.set_attribute ("username", f.username);
          e.set_attribute ("app_id", APP_ID);
          e.set_attribute ("app_name", APP_NAME);
          e.set_attribute ("hashes", get_file_hashes (f));

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Metadata
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          mobius::pod::map metadata;

          metadata.set ("size", f.size);
          metadata.set ("network", "Ares");
          update_metadata (metadata, f.metadata);

          e.set_attribute ("metadata", metadata);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Tags
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.set_tag ("p2p");

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Sources
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.add_source (f.shareh_f);
          e.add_source (f.sharel_f);
          e.add_source (f.torrenth_f);
          e.add_source (f.phashidx_f);
          e.add_source (f.arestra_f);
          e.add_source (f.tempdl_pbthash_f);
          e.add_source (f.tempdl_phash_f);
          e.add_source (f.tempul_udpphash_f);
        }
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save sent files
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_sent_files ()
{
  for (const auto& f : files_)
    {
      if (f.flag_uploaded.is_yes ())
        {
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Create evidence
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto e = item_.new_evidence ("sent-file");

          if (f.upload_started_time)
            e.set_attribute ("timestamp", f.upload_started_time);

          e.set_attribute ("filename", f.filename);
          e.set_attribute ("path", f.path);
          e.set_attribute ("username", f.username);
          e.set_attribute ("app_id", APP_ID);
          e.set_attribute ("app_name", APP_NAME);
          e.set_attribute ("hashes", get_file_hashes (f));

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Metadata
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          mobius::pod::map metadata;
          metadata.set ("flag_downloaded", to_string (f.flag_downloaded));
          metadata.set ("flag_uploaded", to_string (f.flag_uploaded));
          metadata.set ("flag_shared", to_string (f.flag_shared));
          metadata.set ("flag_corrupted", to_string (f.flag_corrupted));
          metadata.set ("flag_completed", to_string (f.flag_completed));

          if (f.shareh_idx)
            metadata.set ("shareh_idx", f.shareh_idx);

          if (f.sharel_idx)
            metadata.set ("sharel_idx", f.sharel_idx);

          if (f.torrenth_idx)
            metadata.set ("torrenth_idx", f.torrenth_idx);

          if (f.phashidx_idx)
            metadata.set ("phashidx_idx", f.phashidx_idx);

          metadata.set ("network", "Ares");
          update_metadata (metadata, f.metadata);

          e.set_attribute ("metadata", metadata);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Tags
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.set_tag ("p2p");

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Sources
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.add_source (f.shareh_f);
          e.add_source (f.sharel_f);
          e.add_source (f.torrenth_f);
          e.add_source (f.phashidx_f);
          e.add_source (f.arestra_f);
          e.add_source (f.tempdl_pbthash_f);
          e.add_source (f.tempdl_phash_f);
          e.add_source (f.tempul_udpphash_f);
        }
    }
}

// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//! \brief Save shared files
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void
evidence_loader_impl::_save_shared_files ()
{
  for (const auto& f : files_)
    {
      if (f.flag_shared.is_yes () || f.flag_shared.is_always ())
        {
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Create evidence
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          auto e = item_.new_evidence ("shared-file");

          e.set_attribute ("username", f.username);
          e.set_attribute ("filename", f.filename);
          e.set_attribute ("path", f.path);
          e.set_attribute ("app_id", APP_ID);
          e.set_attribute ("app_name", APP_NAME);

          std::vector <mobius::pod::data> hashes = {{"sha1", f.hash_sha1}};
          e.set_attribute ("hashes", hashes);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Metadata
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          mobius::pod::map metadata;

          metadata.set ("size", f.size);
          metadata.set ("flag_downloaded", to_string (f.flag_downloaded));
          metadata.set ("flag_uploaded", to_string (f.flag_uploaded));
          metadata.set ("flag_shared", to_string (f.flag_shared));
          metadata.set ("flag_corrupted", to_string (f.flag_corrupted));
          metadata.set ("flag_completed", to_string (f.flag_completed));

          if (f.shareh_idx)
            metadata.set ("shareh_idx", f.shareh_idx);

          if (f.sharel_idx)
            metadata.set ("sharel_idx", f.sharel_idx);

          if (f.torrenth_idx)
            metadata.set ("torrenth_idx", f.torrenth_idx);

          if (f.phashidx_idx)
            metadata.set ("phashidx_idx", f.phashidx_idx);

          metadata.set ("network", "Ares");
          update_metadata (metadata, f.metadata);

          e.set_attribute ("metadata", metadata);

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Tags
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.set_tag ("p2p");

          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          // Sources
          // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
          e.add_source (f.shareh_f);
          e.add_source (f.sharel_f);
          e.add_source (f.torrenth_f);
          e.add_source (f.phashidx_f);
          e.add_source (f.arestra_f);
          e.add_source (f.tempdl_pbthash_f);
          e.add_source (f.tempdl_phash_f);
          e.add_source (f.tempul_udpphash_f);
        }
    }
}*/

} // namespace mobius::extension::app::shareaza