Skip to content

Commit

Permalink
[addons] only allow update from official repos or origin
Browse files Browse the repository at this point in the history
  • Loading branch information
howie-f committed Aug 19, 2020
1 parent 5212aa6 commit 9636019
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 20 deletions.
27 changes: 20 additions & 7 deletions xbmc/addons/AddonManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,16 +310,29 @@ bool CAddonMgr::GetInstallableAddons(VECADDONS& addons, const TYPE &type)

bool CAddonMgr::FindInstallableById(const std::string& addonId, AddonPtr& result)
{
VECADDONS versions;
CSingleLock lock(m_critSection);

CAddonRepos addonRepos(*this);
addonRepos.LoadAddonsFromDatabase(m_database, addonId);

AddonPtr addonToUpdate;

// check for an update if addon is installed already

if (GetAddon(addonId, addonToUpdate, ADDON_UNKNOWN, false))
{
CSingleLock lock(m_critSection);
if (!m_database.FindByAddonId(addonId, versions) || versions.empty())
return false;
return addonRepos.DoAddonUpdateCheck(addonToUpdate, result);
}

result = *std::max_element(versions.begin(), versions.end(),
[](const AddonPtr& a, const AddonPtr& b) { return a->Version() < b->Version(); });
return true;
// get the latest version from all repos if the
// addon is not installed yet (e.g. for addon select dialog)

CLog::Log(
LOGDEBUG,
"CAddonMgr::{}: addon {} is not installed. falling back to get latest version from ALL repos",
__FUNCTION__, addonId);

return addonRepos.GetLatestAddonVersionFromAllRepos(addonId, result);
}

bool CAddonMgr::GetAddonsInternal(const TYPE& type,
Expand Down
15 changes: 13 additions & 2 deletions xbmc/addons/AddonManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ namespace ADDON

/*! \brief Retrieve a specific addon (of a specific type)
\param id the id of the addon to retrieve.
\param addon [out] the retrieved addon pointer - only use if the function returns true.
\param addon[out] the retrieved addon pointer - only use if the function returns true.
\param type type of addon to retrieve - defaults to any type.
\param enabledOnly whether we only want enabled addons - set to false to allow both enabled and disabled addons - defaults to true.
\return true if an addon matching the id of the given type is available and is enabled (if enabledOnly is true).
Expand Down Expand Up @@ -104,7 +104,18 @@ namespace ADDON

bool GetInstallableAddons(VECADDONS& addons, const TYPE &type);

/*! Get the installable addon with the highest version. */
/*! \brief Get the installable addon depending on install rules
* or fall back to highest version.
* \note This function gets called in different contexts. If it's
* called for checking possible updates for already installed addons
* our update restriction rules apply.
* If it's called to (for example) populate an addon-select-dialog
* the addon is not installed yet, and we have to fall back to the
* highest version.
* \param addonId addon to check for update or installation
* \param addon[out] the retrieved addon pointer - only use if the function returns true.
* \return true if an addon matching the id is available.
*/
bool FindInstallableById(const std::string& addonId, AddonPtr& addon);

void AddToUpdateableAddons(AddonPtr &pAddon);
Expand Down
75 changes: 64 additions & 11 deletions xbmc/addons/AddonRepos.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,27 @@ bool CAddonRepos::DoAddonUpdateCheck(const std::shared_ptr<IAddon>& addon,

update.reset();

if (ORIGIN_SYSTEM == addon->Origin())
{
if (!FindAddonAndCheckForUpdate(addon, m_latestOfficialVersions, update))
return false;
}
else
const AddonRepoUpdateMode updateMode =
CAddonSystemSettings::GetInstance().GetAddonRepoUpdateMode();

bool hasOfficialUpdate = FindAddonAndCheckForUpdate(addon, m_latestOfficialVersions, update);

if (ORIGIN_SYSTEM != addon->Origin() && !hasOfficialUpdate) // not a system addon
{
// if the addon is not found in an official repo...
if (!FindAddonAndCheckForUpdate(addon, m_latestOfficialVersions, update))
// If we didn't find an official update
if (IsFromOfficialRepo(addon, true)) // is an official addon
{
if (updateMode == AddonRepoUpdateMode::ANY_REPOSITORY)
if (!FindAddonAndCheckForUpdate(addon, m_latestPrivateVersions, update))
return false;
}
else
{
// ...we move on and check the private/3rd party repo(s)
if (!FindAddonAndCheckForUpdate(addon, m_latestPrivateVersions, update))
return false;
// ...we check for updates in the origin repo only
const auto& repoEntry = m_latestVersionsByRepo.find(addon->Origin());
if (repoEntry != m_latestVersionsByRepo.end())
if (!FindAddonAndCheckForUpdate(addon, repoEntry->second, update))
return false;
}
}

Expand Down Expand Up @@ -240,3 +248,48 @@ bool CAddonRepos::FindAddonAndCheckForUpdate(

return false;
}

bool CAddonRepos::GetLatestVersionByMap(const std::string& addonId,
const std::map<std::string, std::shared_ptr<IAddon>>& map,
std::shared_ptr<IAddon>& result) const
{
const auto& remote = map.find(addonId);
if (remote != map.end()) // is addon in the desired map?
{
result = remote->second;
return true;
}

return false;
}

bool CAddonRepos::GetLatestAddonVersionFromAllRepos(const std::string& addonId,
std::shared_ptr<IAddon>& result) const
{
const AddonRepoUpdateMode updateMode =
CAddonSystemSettings::GetInstance().GetAddonRepoUpdateMode();

bool hasOfficialVersion = GetLatestVersionByMap(addonId, m_latestOfficialVersions, result);

if (hasOfficialVersion)
{
if (updateMode == AddonRepoUpdateMode::ANY_REPOSITORY)
{
std::shared_ptr<IAddon> thirdPartyAddon;

// only use this version if it's higher than the official one
if (GetLatestVersionByMap(addonId, m_latestPrivateVersions, thirdPartyAddon))
{
if (thirdPartyAddon->Version() > result->Version())
result = thirdPartyAddon;
}
}
}
else
{
if (!GetLatestVersionByMap(addonId, m_latestPrivateVersions, result))
return false;
}

return true;
}
21 changes: 21 additions & 0 deletions xbmc/addons/AddonRepos.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ class CAddonRepos
bool DoAddonUpdateCheck(const std::shared_ptr<IAddon>& addon,
std::shared_ptr<IAddon>& update) const;

/*!
* \brief Retrieves the latest version of an addon from all installed repositories
* follows addon origin restriction rules
* \param addonId addon id we're looking the latest version for
* \param[out] result pointer to the found addon
* \return true if a version was found, false otherwise
*/
bool GetLatestAddonVersionFromAllRepos(const std::string& addonId,
std::shared_ptr<IAddon>& result) const;

private:
/*!
* \brief Looks up an addon in a given repository map and
Expand Down Expand Up @@ -128,6 +138,17 @@ class CAddonRepos
const std::shared_ptr<IAddon>& addonToAdd,
std::map<std::string, std::map<std::string, std::shared_ptr<IAddon>>>& map) const;

/*!
* \brief Looks up an addon entry in a specific map
* \param addonId addon we want to retrieve
* \param map the map we're looking into for the wanted addon
* \param[out] result pointer to the found addon, only use when function returns true
* \return true if the addon was found in the map, false otherwise
*/
bool GetLatestVersionByMap(const std::string& addonId,
const std::map<std::string, std::shared_ptr<IAddon>>& map,
std::shared_ptr<IAddon>& result) const;

const CAddonMgr& m_addonMgr;

std::vector<std::shared_ptr<IAddon>> m_allAddons;
Expand Down

0 comments on commit 9636019

Please sign in to comment.