bool CRepository::GetAddonHash(const AddonPtr& addon, std::string& checksum) const { DirList::const_iterator it; for (it = m_dirs.begin();it != m_dirs.end(); ++it) if (URIUtils::PathHasParent(addon->Path(), it->datadir, true)) break; if (it != m_dirs.end()) { if (!it->hashes) { checksum = ""; return true; } if (FetchChecksum(addon->Path() + ".md5", checksum)) { size_t pos = checksum.find_first_of(" \n"); if (pos != std::string::npos) { checksum = checksum.substr(0, pos); return true; } } } return false; }
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); }
bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &type/*=ADDON_UNKNOWN*/, bool enabledOnly /*= true*/) { CSingleLock lock(m_critSection); CStdString xbmcPath = _P("special://xbmc/addons"); cp_status_t status; cp_plugin_info_t *cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status); if (status == CP_OK && cpaddon) { addon = GetAddonFromDescriptor(cpaddon); m_cpluff->release_info(m_cp_context, cpaddon); if (addon && addon.get() && enabledOnly) { if (addon->Type() == ADDON_PVRDLL && addon->Path().Left(xbmcPath.size()).Equals(xbmcPath)) { if (!m_database.IsSystemPVRAddonEnabled(addon->ID())) return false; } else if (m_database.IsAddonDisabled(addon->ID())) return false; } return NULL != addon.get(); } if (cpaddon) m_cpluff->release_info(m_cp_context, cpaddon); return false; }
bool CAddonMgr::CanAddonBeDisabled(const std::string& ID) { if (ID.empty()) return false; CSingleLock lock(m_critSection); // can't disable an already disabled addon if (IsAddonDisabled(ID)) return false; AddonPtr localAddon; // can't disable an addon that isn't installed if (!IsAddonInstalled(ID, localAddon)) return false; // can't disable an addon that is in use if (localAddon->IsInUse()) return false; // installed PVR addons can always be disabled if (localAddon->Type() == ADDON_PVRDLL) return true; std::string systemAddonsPath = CSpecialProtocol::TranslatePath("special://xbmc/addons"); // can't disable system addons if (StringUtils::StartsWith(localAddon->Path(), systemAddonsPath)) return false; return true; }
CRepository::ResolveResult CRepository::ResolvePathAndHash(const AddonPtr& addon) const { std::string const& path = addon->Path(); auto dirIt = std::find_if(m_dirs.begin(), m_dirs.end(), [&path](DirInfo const& dir) { return URIUtils::PathHasParent(path, dir.datadir, true); }); if (dirIt == m_dirs.end()) { CLog::Log(LOGERROR, "Requested path {} not found in known repository directories", path); return {}; } if (dirIt->hashType == CDigest::Type::INVALID) { // We have a path, but need no hash return {path, {}}; } // Do not follow mirror redirect, we want the headers of the redirect response CURL url{path}; url.SetProtocolOption("redirect-limit", "0"); CCurlFile file; if (!file.Open(url)) { CLog::Log(LOGERROR, "Could not fetch addon location and hash from {}", path); return {}; } std::string hashTypeStr = CDigest::TypeToString(dirIt->hashType); // Return the location from the header so we don't have to look it up again // (saves one request per addon install) std::string location = file.GetRedirectURL(); // content-* headers are base64, convert to base16 TypedDigest hash{dirIt->hashType, StringUtils::ToHexadecimal(Base64::Decode(file.GetHttpHeader().GetValue(std::string("content-") + hashTypeStr)))}; if (hash.Empty()) { // Expected hash, but none found -> fall back to old method if (!FetchChecksum(path + "." + hashTypeStr, hash.value) || hash.Empty()) { CLog::Log(LOGERROR, "Failed to find hash for {} from HTTP header and in separate file", path); return {}; } } if (location.empty()) { // Fall back to original URL if we do not get a redirect location = path; } CLog::Log(LOGDEBUG, "Resolved addon path {} to {} hash {}", path, location, hash.value); return {location, hash}; }
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; }
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); }
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; }
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; }
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); }