summaryrefslogtreecommitdiffstats
path: root/xbmc/addons/AddonDatabase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'xbmc/addons/AddonDatabase.cpp')
-rw-r--r--xbmc/addons/AddonDatabase.cpp797
1 files changed, 797 insertions, 0 deletions
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 @@
1/*
2 * Copyright (C) 2005-2013 Team XBMC
3 * http://xbmc.org
4 *
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
8 * any later version.
9 *
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
18 *
19 */
20
21#include "AddonDatabase.h"
22#include "addons/AddonManager.h"
23#include "utils/log.h"
24#include "utils/Variant.h"
25#include "utils/StringUtils.h"
26#include "XBDateTime.h"
27#include "dbwrappers/dataset.h"
28#include "addons/ContextItemAddon.h"
29
30using namespace ADDON;
31using namespace std;
32
33CAddonDatabase::CAddonDatabase()
34{
35}
36
37CAddonDatabase::~CAddonDatabase()
38{
39}
40
41bool CAddonDatabase::Open()
42{
43 return CDatabase::Open();
44}
45
46void CAddonDatabase::CreateTables()
47{
48 CLog::Log(LOGINFO, "create addon table");
49 m_pDS->exec("CREATE TABLE addon (id integer primary key, type text,"
50 "name text, summary text, description text, stars integer,"
51 "path text, addonID text, icon text, version text, "
52 "changelog text, fanart text, author text, disclaimer text,"
53 "minversion text)\n");
54
55 CLog::Log(LOGINFO, "create addonextra table");
56 m_pDS->exec("CREATE TABLE addonextra (id integer, key text, value text)\n");
57
58 CLog::Log(LOGINFO, "create dependencies table");
59 m_pDS->exec("CREATE TABLE dependencies (id integer, addon text, version text, optional boolean)\n");
60
61 CLog::Log(LOGINFO, "create repo table");
62 m_pDS->exec("CREATE TABLE repo (id integer primary key, addonID text,"
63 "checksum text, lastcheck text, version text)\n");
64
65 CLog::Log(LOGINFO, "create addonlinkrepo table");
66 m_pDS->exec("CREATE TABLE addonlinkrepo (idRepo integer, idAddon integer)\n");
67
68 CLog::Log(LOGINFO, "create disabled table");
69 m_pDS->exec("CREATE TABLE disabled (id integer primary key, addonID text)\n");
70
71 CLog::Log(LOGINFO, "create broken table");
72 m_pDS->exec("CREATE TABLE broken (id integer primary key, addonID text, reason text)\n");
73
74 CLog::Log(LOGINFO, "create blacklist table");
75 m_pDS->exec("CREATE TABLE blacklist (id integer primary key, addonID text, version text)\n");
76
77 CLog::Log(LOGINFO, "create package table");
78 m_pDS->exec("CREATE TABLE package (id integer primary key, addonID text, filename text, hash text)\n");
79}
80
81void CAddonDatabase::CreateAnalytics()
82{
83 CLog::Log(LOGINFO, "%s creating indicies", __FUNCTION__);
84 m_pDS->exec("CREATE INDEX idxAddon ON addon(addonID)");
85 m_pDS->exec("CREATE INDEX idxAddonExtra ON addonextra(id)");
86 m_pDS->exec("CREATE INDEX idxDependencies ON dependencies(id)");
87 m_pDS->exec("CREATE UNIQUE INDEX ix_addonlinkrepo_1 ON addonlinkrepo ( idAddon, idRepo )\n");
88 m_pDS->exec("CREATE UNIQUE INDEX ix_addonlinkrepo_2 ON addonlinkrepo ( idRepo, idAddon )\n");
89 m_pDS->exec("CREATE UNIQUE INDEX idxDisabled ON disabled(addonID)");
90 m_pDS->exec("CREATE UNIQUE INDEX idxBroken ON broken(addonID)");
91 m_pDS->exec("CREATE UNIQUE INDEX idxBlack ON blacklist(addonID)");
92 m_pDS->exec("CREATE UNIQUE INDEX idxPackage ON package(filename)");
93}
94
95void CAddonDatabase::UpdateTables(int version)
96{
97 if (version < 16)
98 {
99 m_pDS->exec("CREATE TABLE package (id integer primary key, addonID text, filename text, hash text)\n");
100 }
101 if (version < 17)
102 {
103 m_pDS->exec("DELETE FROM repo");
104 m_pDS->exec("ALTER TABLE repo ADD version text");
105 }
106}
107
108int CAddonDatabase::AddAddon(const AddonPtr& addon,
109 int idRepo)
110{
111 try
112 {
113 if (NULL == m_pDB.get()) return -1;
114 if (NULL == m_pDS.get()) return -1;
115
116 std::string sql = PrepareSQL("insert into addon (id, type, name, summary,"
117 "description, stars, path, icon, changelog, "
118 "fanart, addonID, version, author, disclaimer, minversion)"
119 " values(NULL, '%s', '%s', '%s', '%s', %i,"
120 "'%s', '%s', '%s', '%s', '%s','%s','%s','%s','%s')",
121 TranslateType(addon->Type(),false).c_str(),
122 addon->Name().c_str(), addon->Summary().c_str(),
123 addon->Description().c_str(),addon->Stars(),
124 addon->Path().c_str(), addon->Props().icon.c_str(),
125 addon->ChangeLog().c_str(),addon->FanArt().c_str(),
126 addon->ID().c_str(), addon->Version().asString().c_str(),
127 addon->Author().c_str(),addon->Disclaimer().c_str(),
128 addon->MinVersion().asString().c_str());
129 m_pDS->exec(sql.c_str());
130 int idAddon = (int)m_pDS->lastinsertid();
131
132 sql = PrepareSQL("insert into addonlinkrepo (idRepo, idAddon) values (%i,%i)",idRepo,idAddon);
133 m_pDS->exec(sql.c_str());
134
135 const InfoMap &info = addon->ExtraInfo();
136 for (InfoMap::const_iterator i = info.begin(); i != info.end(); ++i)
137 {
138 sql = PrepareSQL("insert into addonextra(id, key, value) values (%i, '%s', '%s')", idAddon, i->first.c_str(), i->second.c_str());
139 m_pDS->exec(sql.c_str());
140 }
141 const ADDONDEPS &deps = addon->GetDeps();
142 for (ADDONDEPS::const_iterator i = deps.begin(); i != deps.end(); ++i)
143 {
144 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);
145 m_pDS->exec(sql.c_str());
146 }
147 return idAddon;
148 }
149 catch (...)
150 {
151 CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addon->Name().c_str());
152 }
153 return -1;
154}
155
156AddonVersion CAddonDatabase::GetAddonVersion(const std::string &id)
157{
158 AddonVersion maxversion("0.0.0");
159 try
160 {
161 if (NULL == m_pDB.get()) return maxversion;
162 if (NULL == m_pDS2.get()) return maxversion;
163
164 // there may be multiple addons with this id (eg from different repositories) in the database,
165 // so we want to retrieve the latest version. Order by version won't work as the database
166 // won't know that 1.10 > 1.2, so grab them all and order outside
167 std::string sql = PrepareSQL("select version from addon where addonID='%s'",id.c_str());
168 m_pDS2->query(sql.c_str());
169
170 if (m_pDS2->eof())
171 return maxversion;
172
173 while (!m_pDS2->eof())
174 {
175 AddonVersion version(m_pDS2->fv(0).get_asString());
176 if (version > maxversion)
177 maxversion = version;
178 m_pDS2->next();
179 }
180 return maxversion;
181 }
182 catch (...)
183 {
184 CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str());
185 }
186 return maxversion;
187}
188
189bool CAddonDatabase::GetAddon(const std::string& id, AddonPtr& addon)
190{
191 try
192 {
193 if (NULL == m_pDB.get()) return false;
194 if (NULL == m_pDS2.get()) return false;
195
196 // there may be multiple addons with this id (eg from different repositories) in the database,
197 // so we want to retrieve the latest version. Order by version won't work as the database
198 // won't know that 1.10 > 1.2, so grab them all and order outside
199 std::string sql = PrepareSQL("select id,version from addon where addonID='%s'",id.c_str());
200 m_pDS2->query(sql.c_str());
201
202 if (m_pDS2->eof())
203 return false;
204
205 AddonVersion maxversion("0.0.0");
206 int maxid = 0;
207 while (!m_pDS2->eof())
208 {
209 AddonVersion version(m_pDS2->fv(1).get_asString());
210 if (version > maxversion)
211 {
212 maxid = m_pDS2->fv(0).get_asInt();
213 maxversion = version;
214 }
215 m_pDS2->next();
216 }
217 return GetAddon(maxid,addon);
218 }
219 catch (...)
220 {
221 CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str());
222 }
223 addon.reset();
224 return false;
225}
226
227bool CAddonDatabase::GetRepoForAddon(const std::string& addonID, std::string& repo)
228{
229 try
230 {
231 if (NULL == m_pDB.get()) return false;
232 if (NULL == m_pDS2.get()) return false;
233
234 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());
235 m_pDS2->query(sql.c_str());
236 if (!m_pDS2->eof())
237 {
238 repo = m_pDS2->fv(0).get_asString();
239 m_pDS2->close();
240 return true;
241 }
242 }
243 catch (...)
244 {
245 CLog::Log(LOGERROR, "%s failed for addon %s", __FUNCTION__, addonID.c_str());
246 }
247 return false;
248}
249
250bool CAddonDatabase::GetAddon(int id, AddonPtr &addon)
251{
252 try
253 {
254 if (NULL == m_pDB.get()) return false;
255 if (NULL == m_pDS2.get()) return false;
256
257 std::string sql = "SELECT addon.*,"
258 " broken.reason,"
259 " addonextra.key, addonextra.value,"
260 " dependencies.addon, dependencies.version, dependencies.optional"
261 " FROM addon"
262 " LEFT JOIN broken"
263 " ON broken.addonID = addon.addonID"
264 " LEFT JOIN addonextra"
265 " ON addonextra.id = addon.id"
266 " LEFT JOIN dependencies"
267 " ON dependencies.id = addon.id";
268
269 sql += PrepareSQL(" WHERE addon.id=%i", id);
270
271 m_pDS2->query(sql.c_str());
272 if (!m_pDS2->eof())
273 {
274 const dbiplus::query_data &data = m_pDS2->get_result_set().records;
275 const dbiplus::sql_record* const record = data[0];
276 AddonProps props(record->at(addon_addonID).get_asString(),
277 TranslateType(record->at(addon_type).get_asString()),
278 record->at(addon_version).get_asString(),
279 record->at(addon_minversion).get_asString());
280 props.name = record->at(addon_name).get_asString();
281 props.summary = record->at(addon_summary).get_asString();
282 props.description = record->at(addon_description).get_asString();
283 props.changelog = record->at(addon_changelog).get_asString();
284 props.path = record->at(addon_path).get_asString();
285 props.icon = record->at(addon_icon).get_asString();
286 props.fanart = record->at(addon_fanart).get_asString();
287 props.author = record->at(addon_author).get_asString();
288 props.disclaimer = record->at(addon_disclaimer).get_asString();
289 props.broken = record->at(broken_reason).get_asString();
290
291 /* while this is a cartesion join and we'll typically get multiple rows, we rely on the fact that
292 extrainfo and dependencies are maps, so insert() will insert the first instance only */
293 for (dbiplus::query_data::const_iterator i = data.begin(); i != data.end(); ++i)
294 {
295 const dbiplus::sql_record* const record = *i;
296 if (!record->at(addonextra_key).get_asString().empty())
297 props.extrainfo.insert(make_pair(record->at(addonextra_key).get_asString(), record->at(addonextra_value).get_asString()));
298 if (!m_pDS2->fv(dependencies_addon).get_asString().empty())
299 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())));
300 }
301
302 addon = CAddonMgr::AddonFromProps(props);
303 return NULL != addon.get();
304 }
305 }
306 catch (...)
307 {
308 CLog::Log(LOGERROR, "%s failed on addon %i", __FUNCTION__, id);
309 }
310 addon.reset();
311 return false;
312}
313
314bool CAddonDatabase::GetAddons(VECADDONS& addons)
315{
316 try
317 {
318 if (NULL == m_pDB.get()) return false;
319 if (NULL == m_pDS2.get()) return false;
320
321 std::string sql = PrepareSQL("select distinct addonID from addon");
322 m_pDS->query(sql.c_str());
323 while (!m_pDS->eof())
324 {
325 AddonPtr addon;
326 if (GetAddon(m_pDS->fv(0).get_asString(),addon))
327 addons.push_back(addon);
328 m_pDS->next();
329 }
330 m_pDS->close();
331 return true;
332 }
333 catch (...)
334 {
335 CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
336 }
337 return false;
338}
339
340void CAddonDatabase::DeleteRepository(const std::string& id)
341{
342 try
343 {
344 if (NULL == m_pDB.get()) return;
345 if (NULL == m_pDS.get()) return;
346
347 std::string sql = PrepareSQL("select id from repo where addonID='%s'",id.c_str());
348 m_pDS->query(sql.c_str());
349 if (!m_pDS->eof())
350 DeleteRepository(m_pDS->fv(0).get_asInt());
351 }
352 catch (...)
353 {
354 CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str());
355 }
356}
357
358void CAddonDatabase::DeleteRepository(int idRepo)
359{
360 try
361 {
362 if (NULL == m_pDB.get()) return;
363 if (NULL == m_pDS.get()) return;
364
365 std::string sql = PrepareSQL("delete from repo where id=%i",idRepo);
366 m_pDS->exec(sql.c_str());
367 sql = PrepareSQL("delete from addon where id in (select idAddon from addonlinkrepo where idRepo=%i)",idRepo);
368 m_pDS->exec(sql.c_str());
369 sql = PrepareSQL("delete from addonextra where id in (select idAddon from addonlinkrepo where idRepo=%i)",idRepo);
370 m_pDS->exec(sql.c_str());
371 sql = PrepareSQL("delete from dependencies where id in (select idAddon from addonlinkrepo where idRepo=%i)",idRepo);
372 m_pDS->exec(sql.c_str());
373 sql = PrepareSQL("delete from addonlinkrepo where idRepo=%i",idRepo);
374 m_pDS->exec(sql.c_str());
375
376 }
377 catch (...)
378 {
379 CLog::Log(LOGERROR, "%s failed on repo %i", __FUNCTION__, idRepo);
380 }
381}
382
383int CAddonDatabase::AddRepository(const std::string& id, const VECADDONS& addons, const std::string& checksum, const AddonVersion& version)
384{
385 try
386 {
387 if (NULL == m_pDB.get()) return -1;
388 if (NULL == m_pDS.get()) return -1;
389
390 std::string sql;
391 int idRepo = GetRepoChecksum(id,sql);
392 if (idRepo > -1)
393 DeleteRepository(idRepo);
394
395 BeginTransaction();
396
397 CDateTime time = CDateTime::GetCurrentDateTime();
398 sql = PrepareSQL("insert into repo (id,addonID,checksum,lastcheck,version) values (NULL,'%s','%s','%s','%s')",
399 id.c_str(), checksum.c_str(), time.GetAsDBDateTime().c_str(), version.asString().c_str());
400 m_pDS->exec(sql.c_str());
401 idRepo = (int)m_pDS->lastinsertid();
402 for (unsigned int i=0;i<addons.size();++i)
403 AddAddon(addons[i],idRepo);
404
405 CommitTransaction();
406 return idRepo;
407 }
408 catch (...)
409 {
410 CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str());
411 RollbackTransaction();
412 }
413 return -1;
414}
415
416int CAddonDatabase::GetRepoChecksum(const std::string& id, std::string& checksum)
417{
418 try
419 {
420 if (NULL == m_pDB.get()) return -1;
421 if (NULL == m_pDS.get()) return -1;
422
423 std::string strSQL = PrepareSQL("select * from repo where addonID='%s'",id.c_str());
424 m_pDS->query(strSQL.c_str());
425 if (!m_pDS->eof())
426 {
427 checksum = m_pDS->fv("checksum").get_asString();
428 return m_pDS->fv("id").get_asInt();
429 }
430 }
431 catch (...)
432 {
433 CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str());
434 }
435 checksum.clear();
436 return -1;
437}
438
439CDateTime CAddonDatabase::GetRepoTimestamp(const std::string& id)
440{
441 CDateTime date;
442 try
443 {
444 if (NULL == m_pDB.get()) return date;
445 if (NULL == m_pDS.get()) return date;
446
447 std::string strSQL = PrepareSQL("select * from repo where addonID='%s'",id.c_str());
448 m_pDS->query(strSQL.c_str());
449 if (!m_pDS->eof())
450 {
451 date.SetFromDBDateTime(m_pDS->fv("lastcheck").get_asString());
452 return date;
453 }
454 }
455 catch (...)
456 {
457 CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str());
458 }
459 return date;
460}
461
462
463AddonVersion CAddonDatabase::GetRepoVersion(const std::string& id)
464{
465 AddonVersion version("0.0.0");
466 try
467 {
468 if (NULL == m_pDB.get()) return version;
469 if (NULL == m_pDS2.get()) return version;
470
471 std::string strSQL = PrepareSQL("select * from repo where addonID='%s'",id.c_str());
472 m_pDS->query(strSQL.c_str());
473 if (!m_pDS->eof())
474 {
475 return AddonVersion(m_pDS->fv("version").get_asString());
476 }
477 }
478 catch (...)
479 {
480 CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, id.c_str());
481 }
482 return version;
483}
484
485bool CAddonDatabase::SetRepoTimestamp(const std::string& id, const std::string& time, const ADDON::AddonVersion& version)
486{
487 try
488 {
489 if (NULL == m_pDB.get()) return false;
490 if (NULL == m_pDS.get()) return false;
491
492 std::string sql = PrepareSQL("UPDATE repo SET lastcheck='%s', version='%s' WHERE addonID='%s'",
493 time.c_str(), version.asString().c_str(), id.c_str());
494 m_pDS->exec(sql.c_str());
495
496 return true;
497 }
498 catch (...)
499 {
500 CLog::Log(LOGERROR, "%s failed on repo '%s'", __FUNCTION__, id.c_str());
501 }
502 return false;
503}
504
505bool CAddonDatabase::GetRepository(int id, VECADDONS& addons)
506{
507 try
508 {
509 if (NULL == m_pDB.get()) return false;
510 if (NULL == m_pDS.get()) return false;
511
512 std::string strSQL = PrepareSQL("select * from addonlinkrepo where idRepo=%i",id);
513 m_pDS->query(strSQL.c_str());
514 while (!m_pDS->eof())
515 {
516 AddonPtr addon;
517 if (GetAddon(m_pDS->fv("idAddon").get_asInt(),addon))
518 addons.push_back(addon);
519 m_pDS->next();
520 }
521 return true;
522 }
523 catch (...)
524 {
525 CLog::Log(LOGERROR, "%s failed on repo %i", __FUNCTION__, id);
526 }
527 return false;
528}
529
530bool CAddonDatabase::GetRepository(const std::string& id, VECADDONS& addons)
531{
532 try
533 {
534 if (NULL == m_pDB.get()) return false;
535 if (NULL == m_pDS.get()) return false;
536
537 std::string strSQL = PrepareSQL("select id from repo where addonID='%s'",id.c_str());
538 m_pDS->query(strSQL.c_str());
539 if (!m_pDS->eof())
540 return GetRepository(m_pDS->fv(0).get_asInt(),addons);
541 }
542 catch (...)
543 {
544 CLog::Log(LOGERROR, "%s failed on repo %s", __FUNCTION__, id.c_str());
545 }
546 return false;
547}
548
549bool CAddonDatabase::Search(const std::string& search, VECADDONS& addons)
550{
551 try
552 {
553 if (NULL == m_pDB.get()) return false;
554 if (NULL == m_pDS.get()) return false;
555
556 std::string strSQL;
557 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());
558 CLog::Log(LOGDEBUG, "%s query: %s", __FUNCTION__, strSQL.c_str());
559
560 if (!m_pDS->query(strSQL.c_str())) return false;
561 if (m_pDS->num_rows() == 0) return false;
562
563 while (!m_pDS->eof())
564 {
565 AddonPtr addon;
566 GetAddon(m_pDS->fv(0).get_asString(),addon);
567 if (addon->Type() >= ADDON_UNKNOWN+1 && addon->Type() < ADDON_SCRAPER_LIBRARY)
568 addons.push_back(addon);
569 m_pDS->next();
570 }
571 m_pDS->close();
572 return true;
573 }
574 catch (...)
575 {
576 CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
577 }
578 return false;
579}
580
581void CAddonDatabase::SetPropertiesFromAddon(const AddonPtr& addon,
582 CFileItemPtr& pItem)
583{
584 pItem->SetProperty("Addon.ID", addon->ID());
585 pItem->SetProperty("Addon.Type", TranslateType(addon->Type(),true));
586 pItem->SetProperty("Addon.intType", TranslateType(addon->Type()));
587 pItem->SetProperty("Addon.Name", addon->Name());
588 pItem->SetProperty("Addon.Version", addon->Version().asString());
589 pItem->SetProperty("Addon.Summary", addon->Summary());
590 pItem->SetProperty("Addon.Description", addon->Description());
591 pItem->SetProperty("Addon.Creator", addon->Author());
592 pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer());
593 pItem->SetProperty("Addon.Rating", addon->Stars());
594 std::string starrating = StringUtils::Format("rating%d.png", addon->Stars());
595 pItem->SetProperty("Addon.StarRating",starrating);
596 pItem->SetProperty("Addon.Path", addon->Path());
597 if (addon->Props().broken == "DEPSNOTMET")
598 pItem->SetProperty("Addon.Broken", g_localizeStrings.Get(24044));
599 else
600 pItem->SetProperty("Addon.Broken", addon->Props().broken);
601 std::map<std::string,std::string>::iterator it =
602 addon->Props().extrainfo.find("language");
603 if (it != addon->Props().extrainfo.end())
604 pItem->SetProperty("Addon.Language", it->second);
605}
606
607bool CAddonDatabase::DisableAddon(const std::string &addonID, bool disable /* = true */)
608{
609 try
610 {
611 if (NULL == m_pDB.get()) return false;
612 if (NULL == m_pDS.get()) return false;
613
614 if (disable)
615 {
616 if (!IsAddonDisabled(addonID)) // Enabled
617 {
618 std::string sql = PrepareSQL("insert into disabled(id, addonID) values(NULL, '%s')", addonID.c_str());
619 m_pDS->exec(sql);
620
621 // If the addon is a special, call the disabled handler
622 AddonPtr addon;
623 if ((CAddonMgr::Get().GetAddon(addonID, addon, ADDON_SERVICE, false)
624 || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_PVRDLL, false)
625 || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_CONTEXT_ITEM, false)) && addon)
626 addon->OnDisabled();
627
628 return true;
629 }
630 return false; // already disabled or failed query
631 }
632 else
633 {
634 bool disabled = IsAddonDisabled(addonID); //we need to know if service addon is running
635 std::string sql = PrepareSQL("delete from disabled where addonID='%s'", addonID.c_str());
636 m_pDS->exec(sql);
637
638 if (disabled)
639 {
640 // If the addon is a special, call the enabled handler
641 AddonPtr addon;
642 if ((CAddonMgr::Get().GetAddon(addonID, addon, ADDON_SERVICE, false)
643 || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_PVRDLL, false)
644 || CAddonMgr::Get().GetAddon(addonID, addon, ADDON_CONTEXT_ITEM, false)) && addon)
645 addon->OnEnabled();
646 }
647 }
648 return true;
649 }
650 catch (...)
651 {
652 CLog::Log(LOGERROR, "%s failed on addon '%s'", __FUNCTION__, addonID.c_str());
653 }
654 return false;
655}
656
657bool CAddonDatabase::BreakAddon(const std::string &addonID, const std::string& reason)
658{
659 if (reason.empty())
660 return ExecuteQuery(PrepareSQL("DELETE FROM broken WHERE addonID='%s'", addonID.c_str()));
661 else
662 return ExecuteQuery(PrepareSQL("REPLACE INTO broken(addonID, reason) VALUES('%s', '%s')",
663 addonID.c_str(), reason.c_str()));
664}
665
666bool CAddonDatabase::HasAddon(const std::string &addonID)
667{
668 std::string strWhereClause = PrepareSQL("addonID = '%s'", addonID.c_str());
669 std::string strHasAddon = GetSingleValue("addon", "id", strWhereClause);
670
671 return !strHasAddon.empty();
672}
673
674bool CAddonDatabase::IsAddonDisabled(const std::string &addonID)
675{
676 try
677 {
678 if (NULL == m_pDB.get()) return false;
679 if (NULL == m_pDS.get()) return false;
680
681 std::string sql = PrepareSQL("select id from disabled where addonID='%s'", addonID.c_str());
682 m_pDS->query(sql.c_str());
683 bool ret = !m_pDS->eof(); // in the disabled table -> disabled
684 m_pDS->close();
685 return ret;
686 }
687 catch (...)
688 {
689 CLog::Log(LOGERROR, "%s failed on addon %s", __FUNCTION__, addonID.c_str());
690 }
691 return false;
692}
693
694bool CAddonDatabase::IsSystemPVRAddonEnabled(const std::string &addonID)
695{
696 std::string strWhereClause = PrepareSQL("addonID = '%s'", addonID.c_str());
697 std::string strEnabled = GetSingleValue("pvrenabled", "id", strWhereClause);
698
699 return !strEnabled.empty();
700}
701
702std::string CAddonDatabase::IsAddonBroken(const std::string &addonID)
703{
704 return GetSingleValue(PrepareSQL("SELECT reason FROM broken WHERE addonID='%s'", addonID.c_str()));
705}
706
707bool CAddonDatabase::HasDisabledAddons()
708{
709 try
710 {
711 if (NULL == m_pDB.get()) return false;
712 if (NULL == m_pDS.get()) return false;
713
714 m_pDS->query("select count(id) from disabled");
715 bool ret = !m_pDS->eof() && m_pDS->fv(0).get_asInt() > 0; // have rows -> have disabled addons
716 m_pDS->close();
717 return ret;
718 }
719 catch (...)
720 {
721 CLog::Log(LOGERROR, "%s failed", __FUNCTION__);
722 }
723 return false;
724}
725
726bool CAddonDatabase::BlacklistAddon(const std::string& addonID,
727 const std::string& version)
728{
729 try
730 {
731 if (NULL == m_pDB.get()) return false;
732 if (NULL == m_pDS.get()) return false;
733
734 std::string sql = PrepareSQL("insert into blacklist(id, addonID, version) values(NULL, '%s', '%s')", addonID.c_str(),version.c_str());
735 m_pDS->exec(sql);
736
737 return true;
738 }
739 catch (...)
740 {
741 CLog::Log(LOGERROR, "%s failed on addon '%s' for version '%s'", __FUNCTION__, addonID.c_str(),version.c_str());
742 }
743 return false;
744}
745
746bool CAddonDatabase::IsAddonBlacklisted(const std::string& addonID,
747 const std::string& version)
748{
749 std::string where = PrepareSQL("addonID='%s' and version='%s'",addonID.c_str(),version.c_str());
750 return !GetSingleValue("blacklist","addonID",where).empty();
751}
752
753bool CAddonDatabase::RemoveAddonFromBlacklist(const std::string& addonID,
754 const std::string& version)
755{
756 try
757 {
758 if (NULL == m_pDB.get()) return false;
759 if (NULL == m_pDS.get()) return false;
760
761 std::string sql = PrepareSQL("delete from blacklist where addonID='%s' and version='%s'",addonID.c_str(),version.c_str());
762 m_pDS->exec(sql);
763 return true;
764 }
765 catch (...)
766 {
767 CLog::Log(LOGERROR, "%s failed on addon '%s' for version '%s'", __FUNCTION__, addonID.c_str(),version.c_str());
768 }
769 return false;
770}
771
772bool CAddonDatabase::AddPackage(const std::string& addonID,
773 const std::string& packageFileName,
774 const std::string& hash)
775{
776 std::string sql = PrepareSQL("insert into package(id, addonID, filename, hash)"
777 "values(NULL, '%s', '%s', '%s')",
778 addonID.c_str(), packageFileName.c_str(), hash.c_str());
779 return ExecuteQuery(sql);
780}
781
782bool CAddonDatabase::GetPackageHash(const std::string& addonID,
783 const std::string& packageFileName,
784 std::string& hash)
785{
786 std::string where = PrepareSQL("addonID='%s' and filename='%s'",
787 addonID.c_str(), packageFileName.c_str());
788 hash = GetSingleValue("package", "hash", where);
789 return !hash.empty();
790}
791
792bool CAddonDatabase::RemovePackage(const std::string& packageFileName)
793{
794 std::string sql = PrepareSQL("delete from package where filename='%s'", packageFileName.c_str());
795 return ExecuteQuery(sql);
796}
797