From ffca21f2743a7b367fa212799c6e2fea6190dd5d Mon Sep 17 00:00:00 2001 From: manuel Date: Tue, 3 Mar 2015 16:53:59 +0100 Subject: initial commit for kodi master --- xbmc/addons/AddonDatabase.cpp | 797 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 797 insertions(+) create mode 100644 xbmc/addons/AddonDatabase.cpp (limited to 'xbmc/addons/AddonDatabase.cpp') diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp new file mode 100644 index 0000000..69b47ea --- /dev/null +++ b/xbmc/addons/AddonDatabase.cpp @@ -0,0 +1,797 @@ +/* + * Copyright (C) 2005-2013 Team XBMC + * http://xbmc.org + * + * 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 XBMC; see the file COPYING. If not, see + * . + * + */ + +#include "AddonDatabase.h" +#include "addons/AddonManager.h" +#include "utils/log.h" +#include "utils/Variant.h" +#include "utils/StringUtils.h" +#include "XBDateTime.h" +#include "dbwrappers/dataset.h" +#include "addons/ContextItemAddon.h" + +using namespace ADDON; +using namespace std; + +CAddonDatabase::CAddonDatabase() +{ +} + +CAddonDatabase::~CAddonDatabase() +{ +} + +bool CAddonDatabase::Open() +{ + return CDatabase::Open(); +} + +void CAddonDatabase::CreateTables() +{ + CLog::Log(LOGINFO, "create addon table"); + m_pDS->exec("CREATE TABLE addon (id integer primary key, type text," + "name text, summary text, description text, stars integer," + "path text, addonID text, icon text, version text, " + "changelog text, fanart text, author text, disclaimer text," + "minversion text)\n"); + + CLog::Log(LOGINFO, "create addonextra table"); + m_pDS->exec("CREATE TABLE addonextra (id integer, key text, value text)\n"); + + CLog::Log(LOGINFO, "create dependencies table"); + m_pDS->exec("CREATE TABLE dependencies (id integer, addon text, version text, optional boolean)\n"); + + CLog::Log(LOGINFO, "create repo table"); + m_pDS->exec("CREATE TABLE repo (id integer primary key, addonID text," + "checksum text, lastcheck text, version text)\n"); + + CLog::Log(LOGINFO, "create addonlinkrepo table"); + m_pDS->exec("CREATE TABLE addonlinkrepo (idRepo integer, idAddon integer)\n"); + + CLog::Log(LOGINFO, "create disabled table"); + m_pDS->exec("CREATE TABLE disabled (id integer primary key, addonID text)\n"); + + CLog::Log(LOGINFO, "create broken table"); + m_pDS->exec("CREATE TABLE broken (id integer primary key, addonID text, reason text)\n"); + + CLog::Log(LOGINFO, "create blacklist table"); + m_pDS->exec("CREATE TABLE blacklist (id integer primary key, addonID text, version text)\n"); + + CLog::Log(LOGINFO, "create package table"); + m_pDS->exec("CREATE TABLE package (id integer primary key, addonID text, filename text, hash text)\n"); +} + +void CAddonDatabase::CreateAnalytics() +{ + CLog::Log(LOGINFO, "%s creating indicies", __FUNCTION__); + m_pDS->exec("CREATE INDEX idxAddon ON addon(addonID)"); + m_pDS->exec("CREATE INDEX idxAddonExtra ON addonextra(id)"); + m_pDS->exec("CREATE INDEX idxDependencies ON dependencies(id)"); + m_pDS->exec("CREATE UNIQUE INDEX ix_addonlinkrepo_1 ON addonlinkrepo ( idAddon, idRepo )\n"); + m_pDS->exec("CREATE UNIQUE INDEX ix_addonlinkrepo_2 ON addonlinkrepo ( idRepo, idAddon )\n"); + m_pDS->exec("CREATE UNIQUE INDEX idxDisabled ON disabled(addonID)"); + m_pDS->exec("CREATE UNIQUE INDEX idxBroken ON broken(addonID)"); + m_pDS->exec("CREATE UNIQUE INDEX idxBlack ON blacklist(addonID)"); + m_pDS->exec("CREATE UNIQUE INDEX idxPackage ON package(filename)"); +} + +void CAddonDatabase::UpdateTables(int version) +{ + if (version < 16) + { + m_pDS->exec("CREATE TABLE package (id integer primary key, addonID text, filename text, hash text)\n"); + } + if (version < 17) + { + m_pDS->exec("DELETE FROM repo"); + m_pDS->exec("ALTER TABLE repo ADD version text"); + } +} + +int CAddonDatabase::AddAddon(const AddonPtr& addon, + int idRepo) +{ + try + { + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + std::string 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().asString().c_str(), + addon->Author().c_str(),addon->Disclaimer().c_str(), + addon->MinVersion().asString().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.asString().c_str(), i->second.second ? 1 : 0); + m_pDS->exec(sql.c_str()); + } + return idAddon; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str()); + } + return -1; +} + +AddonVersion CAddonDatabase::GetAddonVersion(const std::string &id) +{ + AddonVersion maxversion("0.0.0"); + try + { + if (NULL == m_pDB.get()) return maxversion; + if (NULL == m_pDS2.get()) return maxversion; + + // there may be multiple addons with this id (eg from different repositories) in the database, + // so we want to retrieve the latest version. Order by version won't work as the database + // won't know that 1.10 > 1.2, so grab them all and order outside + std::string sql = PrepareSQL("select version from addon where addonID='%s'",id.c_str()); + m_pDS2->query(sql.c_str()); + + if (m_pDS2->eof()) + return maxversion; + + while (!m_pDS2->eof()) + { + AddonVersion version(m_pDS2->fv(0).get_asString()); + if (version > maxversion) + maxversion = version; + m_pDS2->next(); + } + return maxversion; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str()); + } + return maxversion; +} + +bool CAddonDatabase::GetAddon(const std::string& id, AddonPtr& addon) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS2.get()) return false; + + // there may be multiple addons with this id (eg from different repositories) in the database, + // so we want to retrieve the latest version. Order by version won't work as the database + // won't know that 1.10 > 1.2, so grab them all and order outside + std::string sql = PrepareSQL("select id,version from addon where addonID='%s'",id.c_str()); + m_pDS2->query(sql.c_str()); + + if (m_pDS2->eof()) + return false; + + AddonVersion maxversion("0.0.0"); + int maxid = 0; + while (!m_pDS2->eof()) + { + AddonVersion version(m_pDS2->fv(1).get_asString()); + if (version > maxversion) + { + maxid = m_pDS2->fv(0).get_asInt(); + maxversion = version; + } + m_pDS2->next(); + } + return GetAddon(maxid,addon); + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str()); + } + addon.reset(); + return false; +} + +bool CAddonDatabase::GetRepoForAddon(const std::string& addonID, std::string& repo) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS2.get()) return false; + + std::string sql = PrepareSQL("select repo.addonID from repo join addonlinkrepo on repo.id=addonlinkrepo.idRepo join addon on addonlinkrepo.idAddon=addon.id where addon.addonID like '%s'", addonID.c_str()); + m_pDS2->query(sql.c_str()); + if (!m_pDS2->eof()) + { + repo = m_pDS2->fv(0).get_asString(); + m_pDS2->close(); + return true; + } + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed for addon %s", __FUNCTION__, addonID.c_str()); + } + return false; +} + +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.c_str()); + if (!m_pDS2->eof()) + { + const dbiplus::query_data &data = m_pDS2->get_result_set().records; + const dbiplus::sql_record* const record = data[0]; + AddonProps props(record->at(addon_addonID).get_asString(), + TranslateType(record->at(addon_type).get_asString()), + record->at(addon_version).get_asString(), + record->at(addon_minversion).get_asString()); + props.name = record->at(addon_name).get_asString(); + props.summary = record->at(addon_summary).get_asString(); + props.description = record->at(addon_description).get_asString(); + props.changelog = record->at(addon_changelog).get_asString(); + props.path = record->at(addon_path).get_asString(); + props.icon = record->at(addon_icon).get_asString(); + props.fanart = record->at(addon_fanart).get_asString(); + props.author = record->at(addon_author).get_asString(); + props.disclaimer = record->at(addon_disclaimer).get_asString(); + props.broken = record->at(broken_reason).get_asString(); + + /* 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()) + props.extrainfo.insert(make_pair(record->at(addonextra_key).get_asString(), record->at(addonextra_value).get_asString())); + if (!m_pDS2->fv(dependencies_addon).get_asString().empty()) + props.dependencies.insert(make_pair(record->at(dependencies_addon).get_asString(), make_pair(AddonVersion(record->at(dependencies_version).get_asString()), record->at(dependencies_optional).get_asBool()))); + } + + addon = CAddonMgr::AddonFromProps(props); + return NULL != addon.get(); + } + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon %i", __FUNCTION__, id); + } + addon.reset(); + return false; +} + +bool CAddonDatabase::GetAddons(VECADDONS& addons) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS2.get()) return false; + + std::string sql = PrepareSQL("select distinct addonID from addon"); + m_pDS->query(sql.c_str()); + while (!m_pDS->eof()) + { + AddonPtr addon; + if (GetAddon(m_pDS->fv(0).get_asString(),addon)) + addons.push_back(addon); + m_pDS->next(); + } + m_pDS->close(); + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); + } + return false; +} + +void CAddonDatabase::DeleteRepository(const std::string& id) +{ + try + { + if (NULL == m_pDB.get()) return; + if (NULL == m_pDS.get()) return; + + std::string sql = PrepareSQL("select id from repo where addonID='%s'",id.c_str()); + m_pDS->query(sql.c_str()); + if (!m_pDS->eof()) + DeleteRepository(m_pDS->fv(0).get_asInt()); + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str()); + } +} + +void CAddonDatabase::DeleteRepository(int idRepo) +{ + try + { + if (NULL == m_pDB.get()) return; + if (NULL == m_pDS.get()) return; + + std::string sql = PrepareSQL("delete from repo where id=%i",idRepo); + m_pDS->exec(sql.c_str()); + sql = PrepareSQL("delete from addon where id in (select idAddon from addonlinkrepo where idRepo=%i)",idRepo); + m_pDS->exec(sql.c_str()); + sql = PrepareSQL("delete from addonextra where id in (select idAddon from addonlinkrepo where idRepo=%i)",idRepo); + m_pDS->exec(sql.c_str()); + sql = PrepareSQL("delete from dependencies where id in (select idAddon from addonlinkrepo where idRepo=%i)",idRepo); + m_pDS->exec(sql.c_str()); + sql = PrepareSQL("delete from addonlinkrepo where idRepo=%i",idRepo); + m_pDS->exec(sql.c_str()); + + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo %i", __FUNCTION__, idRepo); + } +} + +int CAddonDatabase::AddRepository(const std::string& id, const VECADDONS& addons, const std::string& checksum, const AddonVersion& version) +{ + try + { + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + std::string sql; + int idRepo = GetRepoChecksum(id,sql); + if (idRepo > -1) + DeleteRepository(idRepo); + + BeginTransaction(); + + CDateTime time = CDateTime::GetCurrentDateTime(); + sql = PrepareSQL("insert into repo (id,addonID,checksum,lastcheck,version) values (NULL,'%s','%s','%s','%s')", + id.c_str(), checksum.c_str(), time.GetAsDBDateTime().c_str(), version.asString().c_str()); + m_pDS->exec(sql.c_str()); + idRepo = (int)m_pDS->lastinsertid(); + for (unsigned int i=0;iquery(strSQL.c_str()); + if (!m_pDS->eof()) + { + checksum = m_pDS->fv("checksum").get_asString(); + return m_pDS->fv("id").get_asInt(); + } + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str()); + } + checksum.clear(); + return -1; +} + +CDateTime CAddonDatabase::GetRepoTimestamp(const std::string& id) +{ + CDateTime date; + try + { + if (NULL == m_pDB.get()) return date; + if (NULL == m_pDS.get()) return date; + + std::string strSQL = PrepareSQL("select * from repo where addonID='%s'",id.c_str()); + m_pDS->query(strSQL.c_str()); + if (!m_pDS->eof()) + { + date.SetFromDBDateTime(m_pDS->fv("lastcheck").get_asString()); + return date; + } + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str()); + } + return date; +} + + +AddonVersion CAddonDatabase::GetRepoVersion(const std::string& id) +{ + AddonVersion version("0.0.0"); + try + { + if (NULL == m_pDB.get()) return version; + if (NULL == m_pDS2.get()) return version; + + std::string strSQL = PrepareSQL("select * from repo where addonID='%s'",id.c_str()); + m_pDS->query(strSQL.c_str()); + if (!m_pDS->eof()) + { + return AddonVersion(m_pDS->fv("version").get_asString()); + } + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str()); + } + return version; +} + +bool CAddonDatabase::SetRepoTimestamp(const std::string& id, const std::string& time, const ADDON::AddonVersion& version) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string sql = PrepareSQL("UPDATE repo SET lastcheck='%s', version='%s' WHERE addonID='%s'", + time.c_str(), version.asString().c_str(), id.c_str()); + m_pDS->exec(sql.c_str()); + + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str()); + } + return false; +} + +bool CAddonDatabase::GetRepository(int id, VECADDONS& addons) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string strSQL = PrepareSQL("select * from addonlinkrepo where idRepo=%i",id); + m_pDS->query(strSQL.c_str()); + while (!m_pDS->eof()) + { + AddonPtr addon; + if (GetAddon(m_pDS->fv("idAddon").get_asInt(),addon)) + addons.push_back(addon); + m_pDS->next(); + } + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo %i", __FUNCTION__, id); + } + return false; +} + +bool CAddonDatabase::GetRepository(const std::string& id, VECADDONS& addons) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string strSQL = PrepareSQL("select id from repo where addonID='%s'",id.c_str()); + m_pDS->query(strSQL.c_str()); + if (!m_pDS->eof()) + return GetRepository(m_pDS->fv(0).get_asInt(),addons); + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on repo %s", __FUNCTION__, id.c_str()); + } + return false; +} + +bool CAddonDatabase::Search(const std::string& search, VECADDONS& addons) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string strSQL; + strSQL=PrepareSQL("SELECT addonID FROM addon WHERE name LIKE '%%%s%%' OR summary LIKE '%%%s%%' OR description LIKE '%%%s%%'", search.c_str(), search.c_str(), search.c_str()); + CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str()); + + if (!m_pDS->query(strSQL.c_str())) return false; + if (m_pDS->num_rows() == 0) return false; + + while (!m_pDS->eof()) + { + AddonPtr addon; + GetAddon(m_pDS->fv(0).get_asString(),addon); + if (addon->Type() >= ADDON_UNKNOWN+1 && addon->Type() < ADDON_SCRAPER_LIBRARY) + addons.push_back(addon); + m_pDS->next(); + } + m_pDS->close(); + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); + } + 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::iterator it = + addon->Props().extrainfo.find("language"); + if (it != addon->Props().extrainfo.end()) + pItem->SetProperty("Addon.Language", it->second); +} + +bool CAddonDatabase::DisableAddon(const std::string &addonID, bool disable /* = true */) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + if (disable) + { + if (!IsAddonDisabled(addonID)) // Enabled + { + std::string sql = PrepareSQL("insert into disabled(id, addonID) values(NULL, '%s')", addonID.c_str()); + m_pDS->exec(sql); + + // If the addon is a special, call the disabled handler + AddonPtr addon; + if ((CAddonMgr::Get().GetAddon(addonID, addon, ADDON_SERVICE, false) + || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_PVRDLL, false) + || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_CONTEXT_ITEM, false)) && addon) + addon->OnDisabled(); + + return true; + } + return false; // already disabled or failed query + } + else + { + bool disabled = IsAddonDisabled(addonID); //we need to know if service addon is running + std::string sql = PrepareSQL("delete from disabled where addonID='%s'", addonID.c_str()); + m_pDS->exec(sql); + + if (disabled) + { + // If the addon is a special, call the enabled handler + AddonPtr addon; + if ((CAddonMgr::Get().GetAddon(addonID, addon, ADDON_SERVICE, false) + || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_PVRDLL, false) + || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_CONTEXT_ITEM, false)) && addon) + addon->OnEnabled(); + } + } + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addonID.c_str()); + } + return false; +} + +bool CAddonDatabase::BreakAddon(const std::string &addonID, const std::string& reason) +{ + if (reason.empty()) + return ExecuteQuery(PrepareSQL("DELETE FROM broken WHERE addonID='%s'", addonID.c_str())); + else + return ExecuteQuery(PrepareSQL("REPLACE INTO broken(addonID, reason) VALUES('%s', '%s')", + addonID.c_str(), reason.c_str())); +} + +bool CAddonDatabase::HasAddon(const std::string &addonID) +{ + std::string strWhereClause = PrepareSQL("addonID = '%s'", addonID.c_str()); + std::string strHasAddon = GetSingleValue("addon", "id", strWhereClause); + + return !strHasAddon.empty(); +} + +bool CAddonDatabase::IsAddonDisabled(const std::string &addonID) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string sql = PrepareSQL("select id from disabled where addonID='%s'", addonID.c_str()); + m_pDS->query(sql.c_str()); + bool ret = !m_pDS->eof(); // in the disabled table -> disabled + m_pDS->close(); + return ret; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, addonID.c_str()); + } + return false; +} + +bool CAddonDatabase::IsSystemPVRAddonEnabled(const std::string &addonID) +{ + std::string strWhereClause = PrepareSQL("addonID = '%s'", addonID.c_str()); + std::string strEnabled = GetSingleValue("pvrenabled", "id", strWhereClause); + + return !strEnabled.empty(); +} + +std::string CAddonDatabase::IsAddonBroken(const std::string &addonID) +{ + return GetSingleValue(PrepareSQL("SELECT reason FROM broken WHERE addonID='%s'", addonID.c_str())); +} + +bool CAddonDatabase::HasDisabledAddons() +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + m_pDS->query("select count(id) from disabled"); + bool ret = !m_pDS->eof() && m_pDS->fv(0).get_asInt() > 0; // have rows -> have disabled addons + m_pDS->close(); + return ret; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); + } + return false; +} + +bool CAddonDatabase::BlacklistAddon(const std::string& addonID, + const std::string& version) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string sql = PrepareSQL("insert into blacklist(id, addonID, version) values(NULL, '%s', '%s')", addonID.c_str(),version.c_str()); + m_pDS->exec(sql); + + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon '%s' for version '%s'", __FUNCTION__, addonID.c_str(),version.c_str()); + } + return false; +} + +bool CAddonDatabase::IsAddonBlacklisted(const std::string& addonID, + const std::string& version) +{ + std::string where = PrepareSQL("addonID='%s' and version='%s'",addonID.c_str(),version.c_str()); + return !GetSingleValue("blacklist","addonID",where).empty(); +} + +bool CAddonDatabase::RemoveAddonFromBlacklist(const std::string& addonID, + const std::string& version) +{ + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + std::string sql = PrepareSQL("delete from blacklist where addonID='%s' and version='%s'",addonID.c_str(),version.c_str()); + m_pDS->exec(sql); + return true; + } + catch (...) + { + CLog::Log(LOGERROR, "%s failed on addon '%s' for version '%s'", __FUNCTION__, addonID.c_str(),version.c_str()); + } + return false; +} + +bool CAddonDatabase::AddPackage(const std::string& addonID, + const std::string& packageFileName, + const std::string& hash) +{ + std::string sql = PrepareSQL("insert into package(id, addonID, filename, hash)" + "values(NULL, '%s', '%s', '%s')", + addonID.c_str(), packageFileName.c_str(), hash.c_str()); + return ExecuteQuery(sql); +} + +bool CAddonDatabase::GetPackageHash(const std::string& addonID, + const std::string& packageFileName, + std::string& hash) +{ + std::string where = PrepareSQL("addonID='%s' and filename='%s'", + addonID.c_str(), packageFileName.c_str()); + hash = GetSingleValue("package", "hash", where); + return !hash.empty(); +} + +bool CAddonDatabase::RemovePackage(const std::string& packageFileName) +{ + std::string sql = PrepareSQL("delete from package where filename='%s'", packageFileName.c_str()); + return ExecuteQuery(sql); +} + -- cgit v1.2.3