Ejemplo n.º 1
0
bool CAddonDatabase::GetAddon(int id, AddonPtr &addon)
{
  try
  {
    if (NULL == m_pDB.get()) return false;
    if (NULL == m_pDS2.get()) return false;

    m_pDS2->query(PrepareSQL("SELECT * FROM addons WHERE id=%i", id));
    if (m_pDS2->eof())
      return false;

    CAddonBuilder builder;
    builder.SetId(m_pDS2->fv("addonID").get_asString());
    builder.SetVersion(AddonVersion(m_pDS2->fv("version").get_asString()));
    builder.SetName(m_pDS2->fv("name").get_asString());
    builder.SetSummary(m_pDS2->fv("summary").get_asString());
    builder.SetDescription(m_pDS2->fv("description").get_asString());
    DeserializeMetadata(m_pDS2->fv("metadata").get_asString(), builder);
    addon = builder.Build();
    return addon != nullptr;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed on addon %i", __FUNCTION__, id);
  }
  return false;
}
Ejemplo n.º 2
0
bool CAddonDatabase::FindByAddonId(const std::string& addonId, ADDON::VECADDONS& result)
{
  try
  {
    if (NULL == m_pDB.get()) return false;
    if (NULL == m_pDS.get()) return false;

    std::string sql = PrepareSQL(
        "SELECT addons.version, addons.name, addons.summary, addons.description, addons.metadata, addons.news,"
        "repo.addonID AS repoID FROM addons "
        "JOIN addonlinkrepo ON addonlinkrepo.idAddon=addons.id "
        "JOIN repo ON repo.id=addonlinkrepo.idRepo "
        "WHERE "
        "repo.checksum IS NOT NULL AND repo.checksum != '' "
        "AND EXISTS (SELECT * FROM installed WHERE installed.addonID=repoID AND installed.enabled=1) "
        "AND addons.addonID='%s'", addonId.c_str());

    VECADDONS addons;
    m_pDS->query(sql.c_str());
    while (!m_pDS->eof())
    {
      CAddonBuilder builder;
      builder.SetId(addonId);
      builder.SetVersion(AddonVersion(m_pDS->fv(0).get_asString()));
      builder.SetName(m_pDS->fv(1).get_asString());
      builder.SetSummary(m_pDS->fv(2).get_asString());
      builder.SetDescription(m_pDS->fv(3).get_asString());
      DeserializeMetadata(m_pDS->fv(4).get_asString(), builder);
      builder.SetChangelog(m_pDS->fv(5).get_asString());
      builder.SetOrigin(m_pDS->fv(6).get_asString());

      auto addon = builder.Build();
      if (addon)
        addons.push_back(std::move(addon));
      else
        CLog::Log(LOGERROR, "CAddonDatabase: failed to build %s", addonId.c_str());
      m_pDS->next();
    }
    m_pDS->close();
    result = std::move(addons);
    return true;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, addonId.c_str());
  }
  return false;
}
Ejemplo n.º 3
0
static void DeserializeMetadata(const std::string& document, CAddonBuilder& builder)
{
  CVariant variant;
  if (!CJSONVariantParser::Parse(document, variant))
    return;

  builder.SetAuthor(variant["author"].asString());
  builder.SetDisclaimer(variant["disclaimer"].asString());
  builder.SetBroken(variant["broken"].asString());
  builder.SetPackageSize(variant["size"].asUnsignedInteger());

  builder.SetPath(variant["path"].asString());
  builder.SetIcon(variant["icon"].asString());

  std::map<std::string, std::string> art;
  for (auto it = variant["art"].begin_map(); it != variant["art"].end_map(); ++it)
    art.emplace(it->first, it->second.asString());
  builder.SetArt(std::move(art));

  std::vector<std::string> screenshots;
  for (auto it = variant["screenshots"].begin_array(); it != variant["screenshots"].end_array(); ++it)
    screenshots.push_back(it->asString());
  builder.SetScreenshots(std::move(screenshots));

  builder.SetType(CAddonInfo::TranslateType(variant["extensions"][0].asString()));

  {
    std::vector<DependencyInfo> deps;
    for (auto it = variant["dependencies"].begin_array(); it != variant["dependencies"].end_array(); ++it)
    {
      deps.emplace_back(
          (*it)["addonId"].asString(),
          AddonVersion((*it)["version"].asString()),
          (*it)["optional"].asBoolean());
    }
    builder.SetDependencies(std::move(deps));
  }

  InfoMap extraInfo;
  for (auto it = variant["extrainfo"].begin_array(); it != variant["extrainfo"].end_array(); ++it)
    extraInfo.emplace((*it)["key"].asString(), (*it)["value"].asString());
  builder.SetExtrainfo(std::move(extraInfo));
}
Ejemplo n.º 4
0
bool CAddonDatabase::GetRepositoryContent(const std::string& id, VECADDONS& addons)
{
  try
  {
    if (NULL == m_pDB.get()) return false;
    if (NULL == m_pDS.get()) return false;

    auto start = XbmcThreads::SystemClockMillis();

    // Ensure that the repositories we fetch from are enabled and valid.
    std::vector<std::string> repoIds;
    {
      std::string sql = PrepareSQL(
          " SELECT repo.id FROM repo"
          " WHERE repo.checksum IS NOT NULL AND repo.checksum != ''"
          " AND EXISTS (SELECT * FROM installed WHERE installed.addonID=repo.addonID AND"
          " installed.enabled=1)");

      if (!id.empty())
        sql += PrepareSQL(" AND repo.addonId='%s'", id.c_str());

      m_pDS->query(sql);
      while (!m_pDS->eof())
      {
        repoIds.emplace_back(m_pDS->fv(0).get_asString());
        m_pDS->next();
      }
    }

    CLog::Log(LOGDEBUG, "CAddonDatabase: SELECT repo.id FROM repo .. took %d ms", XbmcThreads::SystemClockMillis() - start);

    if (repoIds.empty())
    {
      CLog::Log(LOGDEBUG, "CAddonDatabase: no valid repository matching '%s'", id.c_str());
      return false;
    }

    {
      std::string sql = PrepareSQL(
          " SELECT * FROM addons"
          " JOIN addonlinkrepo ON addons.id=addonlinkrepo.idAddon"
          " WHERE addonlinkrepo.idRepo IN (%s)"
          " ORDER BY addons.addonID", StringUtils::Join(repoIds, ",").c_str());

      auto start = XbmcThreads::SystemClockMillis();
      m_pDS->query(sql);
      CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(),
          m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start);
    }

    VECADDONS result;
    while (!m_pDS->eof())
    {
      std::string addonId = m_pDS->fv("addonID").get_asString();
      AddonVersion version(m_pDS->fv("version").get_asString());

      if (!result.empty() && result.back()->ID() == addonId && result.back()->Version() >= version)
      {
        // We already have a version of this addon in our list which is newer.
        m_pDS->next();
        continue;
      }

      CAddonBuilder builder;
      builder.SetId(addonId);
      builder.SetVersion(version);
      builder.SetName(m_pDS->fv("name").get_asString());
      builder.SetSummary(m_pDS->fv("summary").get_asString());
      builder.SetDescription(m_pDS->fv("description").get_asString());
      DeserializeMetadata(m_pDS->fv("metadata").get_asString(), builder);

      auto addon = builder.Build();
      if (addon)
      {
        if (!result.empty() && result.back()->ID() == addonId)
          result.back() = std::move(addon);
        else
          result.push_back(std::move(addon));
      }
      else
        CLog::Log(LOGWARNING, "CAddonDatabase: failed to build %s", addonId.c_str());
      m_pDS->next();
    }
    m_pDS->close();
    addons = std::move(result);

    CLog::Log(LOGDEBUG, "CAddonDatabase::GetAddons took %i ms", XbmcThreads::SystemClockMillis() - start);
    return true;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
  }
  return false;
}
Ejemplo n.º 5
0
bool CAddonDatabase::GetRepositoryContent(const std::string& repoId, VECADDONS& addons)
{
  try
  {
    if (NULL == m_pDB.get()) return false;
    if (NULL == m_pDS.get()) return false;

    auto start = XbmcThreads::SystemClockMillis();

    std::string commonConstraint = PrepareSQL(
        "JOIN addonlinkrepo ON addon.id=addonlinkrepo.idAddon "
        "JOIN repo ON addonlinkrepo.idRepo=repo.id "
        "WHERE repo.checksum IS NOT NULL AND repo.checksum != ''");

    if (!repoId.empty())
      commonConstraint += PrepareSQL(" AND repo.addonId='%s'", repoId.c_str());

    commonConstraint += PrepareSQL(" ORDER BY addon.addonID");

    std::vector<CAddonBuilder> result;
    // Read basic info from the `addon` table
    {
      std::string sql = PrepareSQL("SELECT addon.*, broken.reason FROM addon "
          "LEFT JOIN broken ON broken.addonID=addon.addonID ") + commonConstraint;
      auto start = XbmcThreads::SystemClockMillis();
      m_pDS->query(sql);
      CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(),
          m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start);

      while (!m_pDS->eof())
      {
        std::string addonId = m_pDS->fv(addon_addonID).get_asString();
        AddonVersion version(m_pDS->fv(addon_version).get_asString());

        if (!result.empty() && result.back().GetId() == addonId && result.back().GetVersion() >= version)
        {
          // We already have a version of this addon in our list which is newer.
          m_pDS->next();
          continue;
        }

        CAddonBuilder builder;
        builder.SetId(addonId);
        builder.SetVersion(version);
        builder.SetType(TranslateType(m_pDS->fv(addon_type).get_asString()));
        builder.SetMinVersion(AddonVersion(m_pDS->fv(addon_minversion).get_asString()));
        builder.SetName(m_pDS->fv(addon_name).get_asString());
        builder.SetSummary(m_pDS->fv(addon_summary).get_asString());
        builder.SetDescription(m_pDS->fv(addon_description).get_asString());
        builder.SetChangelog(m_pDS->fv(addon_changelog).get_asString());
        builder.SetDisclaimer(m_pDS->fv(addon_disclaimer).get_asString());
        builder.SetAuthor(m_pDS->fv(addon_author).get_asString());
        builder.SetPath(m_pDS->fv(addon_path).get_asString());
        builder.SetIcon(m_pDS->fv(addon_icon).get_asString());
        builder.SetFanart(m_pDS->fv(addon_fanart).get_asString());
        builder.SetBroken(m_pDS->fv(broken_reason).get_asString());
        if (!result.empty() && result.back().GetId() == addonId)
          result.back() = std::move(builder);
        else
          result.push_back(std::move(builder));
        m_pDS->next();
      }
    }

    // Read extra info.
    {
      std::string sql = PrepareSQL(
          "SELECT addon.addonID as owner, addonextra.key, addonextra.value "
          "FROM addon JOIN addonextra ON addon.id=addonextra.id ") + commonConstraint;

      auto start = XbmcThreads::SystemClockMillis();
      m_pDS->query(sql);
      CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(),
          m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start);

      for (auto& builder : result)
      {
        //move cursor to current or next addon
        while (!m_pDS->eof() && m_pDS->fv(0).get_asString() < builder.GetId())
          m_pDS->next();

        InfoMap extraInfo;
        while (!m_pDS->eof() && m_pDS->fv(0).get_asString() == builder.GetId())
        {
          extraInfo.emplace(m_pDS->fv(1).get_asString(), m_pDS->fv(2).get_asString());
          m_pDS->next();
        }
        builder.SetExtrainfo(std::move(extraInfo));
      }
    }

    // Read dependency info.
    {
      std::string sql = PrepareSQL(
          "SELECT addon.addonID as owner, dependencies.addon, dependencies.version, dependencies.optional "
          "FROM addon JOIN dependencies ON addon.id=dependencies.id ") + commonConstraint;

      auto start = XbmcThreads::SystemClockMillis();
      m_pDS->query(sql);
      CLog::Log(LOGDEBUG, "CAddonDatabase: query %s returned %d rows in %d ms", sql.c_str(),
          m_pDS->num_rows(), XbmcThreads::SystemClockMillis() - start);

      for (auto& builder : result)
      {
        //move cursor to the current or next addon
        while (!m_pDS->eof() && m_pDS->fv(0).get_asString() < builder.GetId())
          m_pDS->next();

        ADDONDEPS dependencies;
        while (!m_pDS->eof() && m_pDS->fv(0).get_asString() == builder.GetId())
        {
          dependencies.emplace(m_pDS->fv(1).get_asString(),
              std::make_pair(AddonVersion(m_pDS->fv(2).get_asString()), m_pDS->fv(3).get_asBool()));
          m_pDS->next();
        }
        builder.SetDependencies(std::move(dependencies));
      }
    }
    m_pDS->close();

    for (auto& builder : result)
    {
      auto addon = builder.Build();
      if (addon)
        addons.push_back(std::move(addon));
    }

    CLog::Log(LOGDEBUG, "CAddonDatabase::GetAddons took %i ms", XbmcThreads::SystemClockMillis() - start);
    return true;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
  }
  return false;
}
Ejemplo n.º 6
0
bool CAddonDatabase::GetAddon(int id, AddonPtr &addon)
{
  try
  {
    if (NULL == m_pDB.get()) return false;
    if (NULL == m_pDS2.get()) return false;

    std::string sql = "SELECT addon.*,"
                      "       broken.reason,"
                      "       addonextra.key, addonextra.value,"
                      "       dependencies.addon, dependencies.version, dependencies.optional"
                      "  FROM addon"
                      "    LEFT JOIN broken"
                      "      ON broken.addonID = addon.addonID"
                      "    LEFT JOIN addonextra"
                      "      ON addonextra.id = addon.id"
                      "    LEFT JOIN dependencies"
                      "      ON dependencies.id = addon.id";

    sql += PrepareSQL(" WHERE addon.id=%i", id);

    m_pDS2->query(sql);
    if (!m_pDS2->eof())
    {
      const dbiplus::query_data &data = m_pDS2->get_result_set().records;
      const dbiplus::sql_record* const record = data[0];

      CAddonBuilder builder;
      builder.SetId(record->at(addon_addonID).get_asString());
      builder.SetType(TranslateType(record->at(addon_type).get_asString()));
      builder.SetVersion(AddonVersion(record->at(addon_version).get_asString()));
      builder.SetMinVersion(AddonVersion(record->at(addon_minversion).get_asString()));
      builder.SetName(record->at(addon_name).get_asString());
      builder.SetSummary(record->at(addon_summary).get_asString());
      builder.SetDescription(record->at(addon_description).get_asString());
      builder.SetChangelog(record->at(addon_changelog).get_asString());
      builder.SetDisclaimer(record->at(addon_disclaimer).get_asString());
      builder.SetAuthor(record->at(addon_author).get_asString());
      builder.SetBroken(record->at(broken_reason).get_asString());
      builder.SetPath(record->at(addon_path).get_asString());
      builder.SetIcon(record->at(addon_icon).get_asString());
      builder.SetFanart(record->at(addon_fanart).get_asString());

      InfoMap extrainfo;
      ADDONDEPS dependencies;
      /* while this is a cartesion join and we'll typically get multiple rows, we rely on the fact that
         extrainfo and dependencies are maps, so insert() will insert the first instance only */
      for (dbiplus::query_data::const_iterator i = data.begin(); i != data.end(); ++i)
      {
        const dbiplus::sql_record* const record = *i;
        if (!record->at(addonextra_key).get_asString().empty())
          extrainfo.insert(std::make_pair(record->at(addonextra_key).get_asString(), record->at(addonextra_value).get_asString()));
        if (!m_pDS2->fv(dependencies_addon).get_asString().empty())
          dependencies.insert(std::make_pair(record->at(dependencies_addon).get_asString(), std::make_pair(AddonVersion(record->at(dependencies_version).get_asString()), record->at(dependencies_optional).get_asBool())));
      }
      builder.SetExtrainfo(std::move(extrainfo));
      builder.SetDependencies(std::move(dependencies));

      addon = builder.Build();
      return NULL != addon.get();
    }
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed on addon %i", __FUNCTION__, id);
  }
  addon.reset();
  return false;
}
Ejemplo n.º 7
0
static void DeserializeMetadata(const std::string& document, CAddonBuilder& builder)
{
  CVariant variant = CJSONVariantParser::Parse(document);

  builder.SetAuthor(variant["author"].asString());
  builder.SetDisclaimer(variant["disclaimer"].asString());
  builder.SetBroken(variant["broken"].asString());
  builder.SetPackageSize(variant["size"].asUnsignedInteger());

  builder.SetPath(variant["path"].asString());
  builder.SetFanart(variant["fanart"].asString());
  builder.SetIcon(variant["icon"].asString());

  std::vector<std::string> screenshots;
  for (auto it = variant["screenshots"].begin_array(); it != variant["screenshots"].end_array(); ++it)
    screenshots.push_back(it->asString());
  builder.SetScreenshots(std::move(screenshots));

  builder.SetType(TranslateType(variant["extensions"][0].asString()));

  ADDONDEPS deps;
  for (auto it = variant["dependencies"].begin_array(); it != variant["dependencies"].end_array(); ++it)
  {
    AddonVersion version((*it)["version"].asString());
    deps.emplace((*it)["addonId"].asString(), std::make_pair(std::move(version), (*it)["optional"].asBoolean()));
  }
  builder.SetDependencies(std::move(deps));

  InfoMap extraInfo;
  for (auto it = variant["extrainfo"].begin_array(); it != variant["extrainfo"].end_array(); ++it)
    extraInfo.emplace((*it)["key"].asString(), (*it)["value"].asString());
  builder.SetExtrainfo(std::move(extraInfo));
}