Пример #1
0
bool CAddonMgr::GetAllOutdatedAddons(VECADDONS &addons, bool enabled /*= true*/)
{
  CSingleLock lock(m_critSection);
  for (int i = ADDON_UNKNOWN+1; i < ADDON_VIZ_LIBRARY; ++i)
  {
    VECADDONS temp;
    if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled))
    {
      AddonPtr repoAddon;
      for (unsigned int j = 0; j < temp.size(); j++)
      {
        // Ignore duplicates due to add-ons with multiple extension points
        bool found = false;
        for (VECADDONS::const_iterator addonIt = addons.begin(); addonIt != addons.end(); addonIt++)
        {
          if ((*addonIt)->ID() == temp[j]->ID())
            found = true;
        }

        if (found || !m_database.GetAddon(temp[j]->ID(), repoAddon))
          continue;

        if (temp[j]->Version() < repoAddon->Version() &&
            !m_database.IsAddonBlacklisted(temp[j]->ID(),
                                           repoAddon->Version().c_str()))
          addons.push_back(repoAddon);
      }
    }
  }
  return !addons.empty();
}
Пример #2
0
bool CAddonInstallJob::Install(const CStdString &installFrom)
{
  CStdString addonFolder(installFrom);
  URIUtils::RemoveSlashAtEnd(addonFolder);
  addonFolder = URIUtils::AddFileToFolder("special://home/addons/",
                                       URIUtils::GetFileName(addonFolder));

  CFileItemList install;
  install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
  install[0]->Select(true);
  CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/");

  AddonPtr addon;
  if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon))
  { // failed extraction or failed to load addon description
    CStdString addonID = URIUtils::GetFileName(addonFolder);
    ReportInstallError(addonID, addonID);
    CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str());
    DeleteAddon(addonFolder);
    return false;
  }

  // resolve dependencies
  CAddonMgr::Get().FindAddons(); // needed as GetDeps() grabs directly from c-pluff via the addon manager
  ADDONDEPS deps = addon->GetDeps();
  CStdString referer;
  referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().c_str());
  for (ADDONDEPS::iterator it  = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first.Equals("xbmc.metadata"))
      continue;
    AddonPtr dependency;
    if (!CAddonMgr::Get().GetAddon(it->first,dependency) || dependency->Version() < it->second.first)
    {
      bool force=(dependency != NULL);
      // dependency is already queued up for install - ::Install will fail
      // instead we wait until the Job has finished. note that we
      // recall install on purpose in case prior installation failed
      if (CAddonInstaller::Get().HasJob(it->first))
      {
        while (CAddonInstaller::Get().HasJob(it->first))
          Sleep(50);
        force = false;
      }
      // don't have the addon or the addon isn't new enough - grab it (no new job for these)
      if (!CAddonInstaller::Get().Install(it->first, force, referer, false))
      {
        DeleteAddon(addonFolder);
        return false;
      }
    }
  }
  return true;
}
Пример #3
0
CFileItemPtr CAddonsDirectory::FileItemFromAddon(AddonPtr &addon, const CStdString &basePath, bool folder)
{
  if (!addon)
    return CFileItemPtr();

  // TODO: This can probably be done more efficiently
  CURL url(basePath);
  url.SetFileName(addon->ID());
  CStdString path(url.Get());
  if (folder)
    URIUtils::AddSlashAtEnd(path);

  CFileItemPtr item(new CFileItem(path, folder));

  CStdString strLabel(addon->Name());
  if (url.GetHostName().Equals("search"))
    strLabel.Format("%s - %s", TranslateType(addon->Type(), true), addon->Name());

  item->SetLabel(strLabel);

  if (!(basePath.Equals("addons://") && addon->Type() == ADDON_REPOSITORY))
    item->SetLabel2(addon->Version().c_str());
  item->SetArt("thumb", addon->Icon());
  item->SetLabelPreformated(true);
  item->SetIconImage("DefaultAddon.png");
  if (!addon->FanArt().IsEmpty() && 
      (URIUtils::IsInternetStream(addon->FanArt()) || 
       CFile::Exists(addon->FanArt())))
  {
    item->SetArt("fanart", addon->FanArt());
  }
  CAddonDatabase::SetPropertiesFromAddon(addon, item);
  return item;
}
Пример #4
0
void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon,
                                           CFileItemPtr& pItem)
{
  pItem->SetProperty("Addon.ID", addon->ID());
  pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true));
  pItem->SetProperty("Addon.intType", TranslateType(addon->Type()));
  pItem->SetProperty("Addon.Name", addon->Name());
  pItem->SetProperty("Addon.Version", addon->Version().asString());
  pItem->SetProperty("Addon.Summary", addon->Summary());
  pItem->SetProperty("Addon.Description", addon->Description());
  pItem->SetProperty("Addon.Creator", addon->Author());
  pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer());
  pItem->SetProperty("Addon.Rating", addon->Stars());
  std::string starrating = StringUtils::Format("rating%d.png", addon->Stars());
  pItem->SetProperty("Addon.StarRating",starrating);
  pItem->SetProperty("Addon.Path", addon->Path());
  if (addon->Props().broken == "DEPSNOTMET")
    pItem->SetProperty("Addon.Broken", g_localizeStrings.Get(24044));
  else
    pItem->SetProperty("Addon.Broken", addon->Props().broken);
  std::map<std::string,std::string>::iterator it = 
                    addon->Props().extrainfo.find("language");
  if (it != addon->Props().extrainfo.end())
    pItem->SetProperty("Addon.Language", it->second);
}
Пример #5
0
void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items, bool reposAsFolders)
{
  CStdString xbmcPath = _P("special://xbmc/addons");
  items.ClearItems();
  for (unsigned i=0; i < addons.size(); i++)
  {
    AddonPtr addon = addons[i];
    CFileItemPtr pItem;
    if (reposAsFolders && addon->Type() == ADDON_REPOSITORY)
      pItem = FileItemFromAddon(addon, "addons://", true);
    else
      pItem = FileItemFromAddon(addon, path.Get(), false);
    AddonPtr addon2;
    if (CAddonMgr::Get().GetAddon(addon->ID(),addon2))
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(305));
    else if ((addon->Type() == ADDON_PVRDLL) && (CStdString(pItem->GetProperty("Addon.Path").asString()).Left(xbmcPath.size()).Equals(xbmcPath)))
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24023));

    if (!addon->Props().broken.IsEmpty())
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24098));
    if (addon2 && addon2->Version() < addon->Version())
    {
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24068));
      pItem->SetProperty("Addon.UpdateAvail", true);
    }
    CAddonDatabase::SetPropertiesFromAddon(addon,pItem);
    items.Add(pItem);
  }
}
Пример #6
0
void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items, bool reposAsFolders)
{
  CStdString xbmcPath = CSpecialProtocol::TranslatePath("special://xbmc/addons");
  items.ClearItems();
  CAddonDatabase db;
  db.Open();
  for (unsigned i=0; i < addons.size(); i++)
  {
    AddonPtr addon = addons[i];
    CFileItemPtr pItem;
    if (reposAsFolders && addon->Type() == ADDON_REPOSITORY)
      pItem = FileItemFromAddon(addon, "addons://", true);
    else
      pItem = FileItemFromAddon(addon, path.Get(), false);
    AddonPtr addon2;
    if (CAddonMgr::Get().GetAddon(addon->ID(),addon2))
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(305));
    else if (db.IsOpen() && db.IsAddonDisabled(addon->ID()))
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24023));

    if (!addon->Props().broken.IsEmpty())
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24098));
    if (addon2 && addon2->Version() < addon->Version())
    {
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24068));
      pItem->SetProperty("Addon.UpdateAvail", true);
    }
    CAddonDatabase::SetPropertiesFromAddon(addon,pItem);
    items.Add(pItem);
  }
  db.Close();
}
Пример #7
0
void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items, bool reposAsFolders)
{
  items.ClearItems();
  for (unsigned i=0; i < addons.size(); i++)
  {
    AddonPtr addon = addons[i];
    CFileItemPtr pItem;
    if (reposAsFolders && addon->Type() == ADDON_REPOSITORY)
      pItem = FileItemFromAddon(addon, "addons://", true);
    else
      pItem = FileItemFromAddon(addon, path.Get(), false);
    AddonPtr addon2;
    if (CAddonMgr::Get().GetAddon(addon->ID(),addon2))
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(305));
    else if (CAddonMgr::Get().IsAddonDisabled(addon->ID()))
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24023));

    if (addon->Props().broken == "DEPSNOTMET")
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24049));
    else if (!addon->Props().broken.empty())
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24098));
    if (addon2 && addon2->Version() < addon->Version())
    {
      pItem->SetProperty("Addon.Status",g_localizeStrings.Get(24068));
      pItem->SetProperty("Addon.UpdateAvail", true);
    }
    CAddonDatabase::SetPropertiesFromAddon(addon,pItem);
    items.Add(pItem);
  }
}
Пример #8
0
std::unique_ptr<CRepository> CRepository::FromExtension(CAddonInfo addonInfo, const cp_extension_t* ext)
{
  DirList dirs;
  AddonVersion version("0.0.0");
  AddonPtr addonver;
  if (CServiceBroker::GetAddonMgr().GetAddon("xbmc.addon", addonver))
    version = addonver->Version();
  for (size_t i = 0; i < ext->configuration->num_children; ++i)
  {
    cp_cfg_element_t* element = &ext->configuration->children[i];
    if(element->name && strcmp(element->name, "dir") == 0)
    {
      DirInfo dir = ParseDirConfiguration(element);
      if (dir.version <= version)
      {
        dirs.push_back(std::move(dir));
      }
    }
  }
  if (!CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "info").empty())
  {
    dirs.push_back(ParseDirConfiguration(ext->configuration));
  }
  return std::unique_ptr<CRepository>(new CRepository(std::move(addonInfo), std::move(dirs)));
}
Пример #9
0
bool CRepositoryUpdateJob::DoWork()
{
  CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checking for updates.", m_repo->ID().c_str());
  CAddonDatabase database;
  database.Open();

  std::string oldChecksum;
  if (database.GetRepoChecksum(m_repo->ID(), oldChecksum) == -1)
    oldChecksum = "";

  std::string newChecksum;
  VECADDONS addons;
  auto status = m_repo->FetchIfChanged(oldChecksum, newChecksum, addons);

  database.SetLastChecked(m_repo->ID(), m_repo->Version(),
      CDateTime::GetCurrentDateTime().GetAsDBDateTime());

  MarkFinished();

  if (status == CRepository::STATUS_ERROR)
    return false;

  if (status == CRepository::STATUS_NOT_MODIFIED)
  {
    CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checksum not changed.", m_repo->ID().c_str());
    return true;
  }

  //Invalidate art.
  {
    CTextureDatabase textureDB;
    textureDB.Open();
    textureDB.BeginMultipleExecute();

    for (const auto& addon : addons)
    {
      AddonPtr oldAddon;
      if (database.GetAddon(addon->ID(), oldAddon) && addon->Version() > oldAddon->Version())
      {
        if (!oldAddon->Icon().empty() || !oldAddon->Art().empty() || !oldAddon->Screenshots().empty())
          CLog::Log(LOGDEBUG, "CRepository: invalidating cached art for '%s'", addon->ID().c_str());

        if (!oldAddon->Icon().empty())
          textureDB.InvalidateCachedTexture(oldAddon->Icon());

        for (const auto& path : oldAddon->Screenshots())
          textureDB.InvalidateCachedTexture(path);

        for (const auto& art : oldAddon->Art())
          textureDB.InvalidateCachedTexture(art.second);
      }
    }
    textureDB.CommitMultipleExecute();
  }

  database.UpdateRepositoryContent(m_repo->ID(), m_repo->Version(), newChecksum, addons);
  return true;
}
Пример #10
0
int CAddonDatabase::AddAddon(const AddonPtr& addon,
                             int idRepo)
{
  try
  {
    if (NULL == m_pDB.get()) return -1;
    if (NULL == m_pDS.get()) return -1;

    bool bDisablePVRAddon = addon->Type() == ADDON_PVRDLL && !HasAddon(addon->ID());

    CStdString sql = PrepareSQL("insert into addon (id, type, name, summary,"
                               "description, stars, path, icon, changelog, "
                               "fanart, addonID, version, author, disclaimer, minversion)"
                               " values(NULL, '%s', '%s', '%s', '%s', %i,"
                               "'%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s')",
                               TranslateType(addon->Type(),false).c_str(),
                               addon->Name().c_str(), addon->Summary().c_str(),
                               addon->Description().c_str(),addon->Stars(),
                               addon->Path().c_str(), addon->Props().icon.c_str(),
                               addon->ChangeLog().c_str(),addon->FanArt().c_str(),
                               addon->ID().c_str(), addon->Version().c_str(),
                               addon->Author().c_str(),addon->Disclaimer().c_str(),
                               addon->MinVersion().c_str());
    m_pDS->exec(sql.c_str());
    int idAddon = (int)m_pDS->lastinsertid();

    sql = PrepareSQL("insert into addonlinkrepo (idRepo, idAddon) values (%i,%i)",idRepo,idAddon);
    m_pDS->exec(sql.c_str());

    const InfoMap &info = addon->ExtraInfo();
    for (InfoMap::const_iterator i = info.begin(); i != info.end(); ++i)
    {
      sql = PrepareSQL("insert into addonextra(id, key, value) values (%i, '%s', '%s')", idAddon, i->first.c_str(), i->second.c_str());
      m_pDS->exec(sql.c_str());
    }
    const ADDONDEPS &deps = addon->GetDeps();
    for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i)
    {
      sql = PrepareSQL("insert into dependencies(id, addon, version, optional) values (%i, '%s', '%s', %i)", idAddon, i->first.c_str(), i->second.first.c_str(), i->second.second ? 1 : 0);
      m_pDS->exec(sql.c_str());
    }
    // these need to be configured
    if (bDisablePVRAddon)
      DisableAddon(addon->ID(), true);
    return idAddon;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str());
  }
  return -1;
}
Пример #11
0
bool CAddonMgr::GetAllOutdatedAddons(VECADDONS &addons, bool enabled /*= true*/)
{
  CSingleLock lock(m_critSection);
  for (int i = ADDON_UNKNOWN+1; i < ADDON_VIZ_LIBRARY; ++i)
  {
    VECADDONS temp;
    if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled))
    {
      AddonPtr repoAddon;
      for (unsigned int j = 0; j < temp.size(); j++)
      {
        if (!m_database.GetAddon(temp[j]->ID(), repoAddon))
          continue;

        if (temp[j]->Version() < repoAddon->Version() &&
            !m_database.IsAddonBlacklisted(temp[j]->ID(),
                                           repoAddon->Version().c_str()))
          addons.push_back(repoAddon);
      }
    }
  }
  return !addons.empty();
}
Пример #12
0
void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon,
                                           CFileItemPtr& pItem)
{
  pItem->SetProperty("Addon.ID", addon->ID());
  pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true));
  pItem->SetProperty("Addon.intType", TranslateType(addon->Type()));
  pItem->SetProperty("Addon.Name", addon->Name());
  pItem->SetProperty("Addon.Version", addon->Version().c_str());
  pItem->SetProperty("Addon.Summary", addon->Summary());
  pItem->SetProperty("Addon.Description", addon->Description());
  pItem->SetProperty("Addon.Creator", addon->Author());
  pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer());
  pItem->SetProperty("Addon.Rating", addon->Stars());
  CStdString starrating;
  starrating.Format("rating%d.png", addon->Stars());
  pItem->SetProperty("Addon.StarRating",starrating);
  pItem->SetProperty("Addon.Path", addon->Path());
  pItem->SetProperty("Addon.Broken", addon->Props().broken);
}
Пример #13
0
int CAddonDatabase::AddAddon(const AddonPtr& addon,
                             int idRepo)
{
  try
  {
    if (NULL == m_pDB.get()) return -1;
    if (NULL == m_pDS.get()) return -1;

    CStdString sql = PrepareSQL("insert into addon (id, type, name, summary,"
                               "description, stars, path, icon, changelog, "
                               "fanart, addonID, version, author, disclaimer)"
                               " values(NULL, '%s', '%s', '%s', '%s', %i,"
                               "'%s', '%s', '%s', '%s', '%s','%s','%s','%s')",
                               TranslateType(addon->Type(),false).c_str(),
                               addon->Name().c_str(), addon->Summary().c_str(),
                               addon->Description().c_str(),addon->Stars(),
                               addon->Path().c_str(), addon->Props().icon.c_str(),
                               addon->ChangeLog().c_str(),addon->FanArt().c_str(),
                               addon->ID().c_str(), addon->Version().str.c_str(),
                               addon->Author().c_str(),addon->Disclaimer().c_str());
    m_pDS->exec(sql.c_str());
    int idAddon = (int)m_pDS->lastinsertid();

    sql = PrepareSQL("insert into addonlinkrepo (idRepo, idAddon) values (%i,%i)",idRepo,idAddon);
    m_pDS->exec(sql.c_str());

    const InfoMap &info = addon->ExtraInfo();
    for (InfoMap::const_iterator i = info.begin(); i != info.end(); ++i)
    {
      sql = PrepareSQL("insert into addonextra(id, key, value) values (%i, '%s', '%s')", idAddon, i->first.c_str(), i->second.c_str());
      m_pDS->exec(sql.c_str());
    }
    return idAddon;
  }
  catch (...)
  {
    CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str());
  }
  return -1;
}
Пример #14
0
bool CAddonInstallJob::Install(const CStdString &installFrom)
{
  CStdString addonFolder(installFrom);
  URIUtils::RemoveSlashAtEnd(addonFolder);
  addonFolder = URIUtils::AddFileToFolder("special://home/addons/",
                                       URIUtils::GetFileName(addonFolder));

  CFileItemList install;
  install.Add(CFileItemPtr(new CFileItem(installFrom, true)));
  install[0]->Select(true);
  CFileOperationJob job(CFileOperationJob::ActionReplace, install, "special://home/addons/");

  AddonPtr addon;
  if (!job.DoWork() || !CAddonMgr::Get().LoadAddonDescription(addonFolder, addon))
  { // failed extraction or failed to load addon description
    CStdString addonID = URIUtils::GetFileName(addonFolder);
    ReportInstallError(addonID, addonID);
    CLog::Log(LOGERROR,"Could not read addon description of %s", addonID.c_str());
    CFileItemList list;
    list.Add(CFileItemPtr(new CFileItem(addonFolder, true)));
    list[0]->Select(true);
    CJobManager::GetInstance().AddJob(new CFileOperationJob(CFileOperationJob::ActionDelete, list, ""), NULL);
    return false;
  }

  // resolve dependencies
  ADDONDEPS deps = addon->GetDeps();
  CStdString referer;
  referer.Format("Referer=%s-%s.zip",addon->ID().c_str(),addon->Version().str.c_str());
  for (ADDONDEPS::iterator it  = deps.begin(); it != deps.end(); ++it)
  {
    if (it->first.Equals("xbmc.metadata"))
      continue;
    AddonPtr dependency;
    if (!CAddonMgr::Get().GetAddon(it->first,dependency))
      CAddonInstaller::Get().Install(it->first, false, referer, false); // no new job for these
  }
  return true;
}
Пример #15
0
static CVariant Serialize(const AddonPtr& addon)
{
  CVariant variant;
  variant["addonid"] = addon->ID();
  variant["type"] = CAddonInfo::TranslateType(addon->Type(), false);
  variant["name"] = addon->Name();
  variant["version"] = addon->Version().asString();
  variant["summary"] = addon->Summary();
  variant["description"] = addon->Description();
  variant["path"] = addon->Path();
  variant["author"] = addon->Author();
  variant["thumbnail"] = addon->Icon();
  variant["disclaimer"] = addon->Disclaimer();
  variant["fanart"] = addon->FanArt();

  variant["dependencies"] = CVariant(CVariant::VariantTypeArray);
  for (const auto& dep : addon->GetDependencies())
  {
    CVariant info(CVariant::VariantTypeObject);
    info["addonid"] = dep.id;
    info["version"] = dep.requiredVersion.asString();
    info["optional"] = dep.optional;
    variant["dependencies"].push_back(std::move(info));
  }
  if (addon->Broken().empty())
    variant["broken"] = false;
  else
    variant["broken"] = addon->Broken();
  variant["extrainfo"] = CVariant(CVariant::VariantTypeArray);
  for (const auto& kv : addon->ExtraInfo())
  {
    CVariant info(CVariant::VariantTypeObject);
    info["key"] = kv.first;
    info["value"] = kv.second;
    variant["extrainfo"].push_back(std::move(info));
  }
  variant["rating"] = -1;
  return variant;
}
Пример #16
0
void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon,
                                           CFileItemPtr& pItem)
{
  pItem->SetProperty("Addon.ID", addon->ID());
  pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true));
  pItem->SetProperty("Addon.intType", TranslateType(addon->Type()));
  pItem->SetProperty("Addon.Name", addon->Name());
  pItem->SetProperty("Addon.Version", addon->Version().c_str());
  pItem->SetProperty("Addon.Summary", addon->Summary());
  pItem->SetProperty("Addon.Description", addon->Description());
  pItem->SetProperty("Addon.Creator", addon->Author());
  pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer());
  pItem->SetProperty("Addon.Rating", addon->Stars());
  CStdString starrating;
  starrating.Format("rating%d.png", addon->Stars());
  pItem->SetProperty("Addon.StarRating",starrating);
  pItem->SetProperty("Addon.Path", addon->Path());
  pItem->SetProperty("Addon.Broken", addon->Props().broken);
  std::map<CStdString,CStdString>::iterator it = 
                    addon->Props().extrainfo.find("language");
  if (it != addon->Props().extrainfo.end())
    pItem->SetProperty("Addon.Language", it->second);
}
Пример #17
0
std::unique_ptr<CRepository> CRepository::FromExtension(CAddonInfo addonInfo, const cp_extension_t* ext)
{
  DirList dirs;
  AddonVersion version("0.0.0");
  AddonPtr addonver;
  if (CServiceBroker::GetAddonMgr().GetAddon("xbmc.addon", addonver))
    version = addonver->Version();
  for (size_t i = 0; i < ext->configuration->num_children; ++i)
  {
    if(ext->configuration->children[i].name &&
       strcmp(ext->configuration->children[i].name, "dir") == 0)
    {
      AddonVersion min_version(CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "@minversion"));
      if (min_version <= version)
      {
        DirInfo dir;
        dir.version = min_version;
        dir.checksum = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "checksum");
        dir.info = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "info");
        dir.datadir = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "datadir");
        dir.hashes = CServiceBroker::GetAddonMgr().GetExtValue(&ext->configuration->children[i], "hashes") == "true";
        dirs.push_back(std::move(dir));
      }
    }
  }
  if (!CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "info").empty())
  {
    DirInfo info;
    info.checksum = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "checksum");
    info.info = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "info");
    info.datadir = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "datadir");
    info.hashes = CServiceBroker::GetAddonMgr().GetExtValue(ext->configuration, "hashes") == "true";
    dirs.push_back(std::move(info));
  }
  return std::unique_ptr<CRepository>(new CRepository(std::move(addonInfo), std::move(dirs)));
}
Пример #18
0
bool CRepositoryUpdateJob::DoWork()
{
  CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checking for updates.", m_repo->ID().c_str());
  CAddonDatabase database;
  database.Open();

  std::string oldChecksum;
  if (database.GetRepoChecksum(m_repo->ID(), oldChecksum) == -1)
    oldChecksum = "";

  std::string newChecksum;
  VECADDONS addons;
  auto status = m_repo->FetchIfChanged(oldChecksum, newChecksum, addons);

  database.SetLastChecked(m_repo->ID(), m_repo->Version(),
      CDateTime::GetCurrentDateTime().GetAsDBDateTime());

  MarkFinished();

  if (status == CRepository::STATUS_ERROR)
    return false;

  if (status == CRepository::STATUS_NOT_MODIFIED)
  {
    CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] checksum not changed.", m_repo->ID().c_str());
    return true;
  }

  //Invalidate art.
  {
    CTextureDatabase textureDB;
    textureDB.Open();
    textureDB.BeginMultipleExecute();

    for (const auto& addon : addons)
    {
      AddonPtr oldAddon;
      if (database.GetAddon(addon->ID(), oldAddon) && addon->Version() > oldAddon->Version())
      {
        if (!oldAddon->Icon().empty() || !oldAddon->FanArt().empty() || !oldAddon->Screenshots().empty())
          CLog::Log(LOGDEBUG, "CRepository: invalidating cached art for '%s'", addon->ID().c_str());
        if (!oldAddon->Icon().empty())
          textureDB.InvalidateCachedTexture(oldAddon->Icon());
        if (!oldAddon->FanArt().empty())
          textureDB.InvalidateCachedTexture(oldAddon->Icon());
        for (const auto& path : oldAddon->Screenshots())
          textureDB.InvalidateCachedTexture(path);
      }
    }
    textureDB.CommitMultipleExecute();
  }

  database.UpdateRepositoryContent(m_repo->ID(), m_repo->Version(), newChecksum, addons);

  //Notify about broken status changes
  for (const auto& addon : addons)
  {
    AddonPtr localAddon;
    if (!CAddonMgr::GetInstance().GetAddon(addon->ID(), localAddon))
      continue;

    if (localAddon && localAddon->Version() > addon->Version())
      //We have a newer version locally
      continue;

    AddonPtr oldAddon;
    database.GetAddon(addon->ID(), oldAddon);

    if (database.GetAddonVersion(addon->ID()).first > addon->Version())
      //Newer version in db (ie. in a different repo)
      continue;

    std::string broken = addon->Broken();
    bool isBroken = !addon->Broken().empty();
    bool isBrokenInDb = oldAddon && !oldAddon->Broken().empty();
    if (isBroken && !isBrokenInDb)
    {
      //newly broken
      if (HELPERS::ShowYesNoDialogLines(CVariant{addon->Name()}, CVariant{24096}, CVariant{24097}, CVariant{""})
        == DialogResponse::YES)
      {
        CAddonMgr::GetInstance().DisableAddon(addon->ID());
      }

      CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' marked broken. reason: \"%s\"",
           m_repo->ID().c_str(), addon->ID().c_str(), broken.c_str());

      CEventLog::GetInstance().Add(EventPtr(new CAddonManagementEvent(addon, 24096)));
    }
    else if (!isBroken && isBrokenInDb)
    {
      //Unbroken
      CLog::Log(LOGDEBUG, "CRepositoryUpdateJob[%s] addon '%s' unbroken",
          m_repo->ID().c_str(), addon->ID().c_str());
    }
  }
  return true;
}