Пример #1
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);
  }
}
Пример #2
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);
}
Пример #3
0
bool CAddonMgr::GetAllOutdatedAddons(VECADDONS &addons, bool getLocalVersion /*= false*/)
{
  CSingleLock lock(m_critSection);
  for (int i = ADDON_UNKNOWN+1; i < ADDON_MAX; ++i)
  {
    VECADDONS temp;
    if (CAddonMgr::Get().GetAddons((TYPE)i, temp, true))
    {
      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().asString().c_str()))
        {
          if (getLocalVersion)
            repoAddon->Props().version = temp[j]->Version();
          addons.push_back(repoAddon);
        }
      }
    }
  }
  return !addons.empty();
}
Пример #4
0
bool CAddonInstaller::InstallFromZip(const std::string &path)
{
  if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER))
    return false;

  // grab the descriptive XML document from the zip, and read it in
  CFileItemList items;
  // BUG: some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol
  CURL pathToUrl(path);
  CURL zipDir = URIUtils::CreateArchivePath("zip", pathToUrl, "");
  if (!CDirectory::GetDirectory(zipDir, items) || items.Size() != 1 || !items[0]->m_bIsFolder)
  {
    CGUIDialogKaiToast::QueueNotification("", path, g_localizeStrings.Get(24045), TOAST_DISPLAY_TIME, false);
    return false;
  }

  // TODO: possibly add support for github generated zips here?
  std::string archive = URIUtils::AddFileToFolder(items[0]->GetPath(), "addon.xml");

  CXBMCTinyXML xml;
  AddonPtr addon;
  if (xml.LoadFile(archive) && CAddonMgr::Get().LoadAddonDescriptionFromMemory(xml.RootElement(), addon))
  {
    // set the correct path
    addon->Props().path = items[0]->GetPath();
    addon->Props().icon = URIUtils::AddFileToFolder(items[0]->GetPath(), "icon.png");

    // install the addon
    return DoInstall(addon);
  }
  CGUIDialogKaiToast::QueueNotification("", path, g_localizeStrings.Get(24045), TOAST_DISPLAY_TIME, false);
  return false;
}
Пример #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
bool CAddonInstaller::InstallFromZip(const CStdString &path)
{
  // grab the descriptive XML document from the zip, and read it in
  CFileItemList items;
  // BUG: some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol
  CStdString zipDir;
  URIUtils::CreateArchivePath(zipDir, "zip", path, "");
  if (!CDirectory::GetDirectory(zipDir, items) || items.Size() != 1 || !items[0]->m_bIsFolder)
  {
    CGUIDialogKaiToast::QueueNotification("", path, g_localizeStrings.Get(24045), TOAST_DISPLAY_TIME, false);
    return false;
  }

  // TODO: possibly add support for github generated zips here?
  CStdString archive = URIUtils::AddFileToFolder(items[0]->GetPath(), "addon.xml");

  TiXmlDocument xml;
  AddonPtr addon;
  if (xml.LoadFile(archive) && CAddonMgr::Get().LoadAddonDescriptionFromMemory(xml.RootElement(), addon))
  {
    // set the correct path
    addon->Props().path = path;

    // install the addon
    return DoInstall(addon);
  }
  CGUIDialogKaiToast::QueueNotification("", path, g_localizeStrings.Get(24045), TOAST_DISPLAY_TIME, false);
  return false;
}
Пример #8
0
bool CAddonInstaller::InstallFromZip(const CStdString &path)
{
  // grab the descriptive XML document from the zip, and read it in
  CFileItemList items;
  // BUG: some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol
  CStdString zipDir;
  URIUtils::CreateArchivePath(zipDir, "zip", path, "");
  if (!CDirectory::GetDirectory(zipDir, items) || items.Size() != 1 || !items[0]->m_bIsFolder)
    return false;

  // TODO: possibly add support for github generated zips here?
  CStdString archive = URIUtils::AddFileToFolder(items[0]->m_strPath, "addon.xml");

  TiXmlDocument xml;
  AddonPtr addon;
  if (xml.LoadFile(archive) && CAddonMgr::Get().LoadAddonDescriptionFromMemory(xml.RootElement(), addon))
  {
    // set the correct path
    addon->Props().path = path;

    // install the addon
    CSingleLock lock(m_critSection);
    if (m_downloadJobs.find(addon->ID()) != m_downloadJobs.end())
      return false;

    unsigned int jobID = CJobManager::GetInstance().AddJob(new CAddonInstallJob(addon), this);
    m_downloadJobs.insert(make_pair(addon->ID(), CDownloadJob(jobID)));
    return true;
  }
  return false;
}
Пример #9
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;
}
Пример #10
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);
}
Пример #11
0
bool CAddonMgr::CanAddonBeInstalled(const AddonPtr& addon)
{
  if (addon == NULL)
    return false;

  CSingleLock lock(m_critSection);
  // can't install already installed addon
  if (IsAddonInstalled(addon->ID()))
    return false;

  // can't install broken addons
  if (!addon->Props().broken.empty())
    return false;

  return true;
}
Пример #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
void CAddonsOperations::FillDetails(AddonPtr addon, const CVariant& fields, CVariant &result, CAddonDatabase &addondb, bool append /* = false */)
{
    if (addon.get() == NULL)
        return;

    CVariant addonInfo;
    addon->Props().Serialize(addonInfo);

    CVariant object;
    object["addonid"] = addonInfo["addonid"];
    object["type"] = addonInfo["type"];

    for (unsigned int index = 0; index < fields.size(); index++)
    {
        string field = fields[index].asString();

        // we need to manually retrieve the enabled state of every addon
        // from the addon database because it can't be read from addon.xml
        if (field == "enabled")
        {
            object[field] = !CAddonMgr::GetInstance().IsAddonDisabled(addon->ID());
        }
        else if (field == "fanart" || field == "thumbnail")
        {
            std::string url = addonInfo[field].asString();
            // We need to check the existence of fanart and thumbnails as the addon simply
            // holds where the art will be, not whether it exists.
            bool needsRecaching;
            std::string image = CTextureCache::GetInstance().CheckCachedImage(url, false, needsRecaching);
            if (!image.empty() || CFile::Exists(url))
                object[field] = CTextureUtils::GetWrappedImageURL(url);
            else
                object[field] = "";
        }
        else if (addonInfo.isMember(field))
            object[field] = addonInfo[field];
    }

    if (append)
        result.append(object);
    else
        result = object;
}
Пример #14
0
bool CAddonInstaller::InstallFromZip(const std::string &path)
{
  if (!g_passwordManager.CheckMenuLock(WINDOW_ADDON_BROWSER))
    return false;

  CLog::Log(LOGDEBUG, "CAddonInstaller: installing from zip '%s'", CURL::GetRedacted(path).c_str());

  // grab the descriptive XML document from the zip, and read it in
  CFileItemList items;
  // BUG: some zip files return a single item (root folder) that we think is stored, so we don't use the zip:// protocol
  CURL pathToUrl(path);
  CURL zipDir = URIUtils::CreateArchivePath("zip", pathToUrl, "");
  if (!CDirectory::GetDirectory(zipDir, items) || items.Size() != 1 || !items[0]->m_bIsFolder)
  {
    CEventLog::GetInstance().AddWithNotification(
      EventPtr(new CNotificationEvent(EventLevelError, 24045,
                   StringUtils::Format(g_localizeStrings.Get(24143).c_str(), path.c_str()))), false);
    return false;
  }

  // TODO: possibly add support for github generated zips here?
  std::string archive = URIUtils::AddFileToFolder(items[0]->GetPath(), "addon.xml");

  CXBMCTinyXML xml;
  AddonPtr addon;
  if (xml.LoadFile(archive) && CAddonMgr::GetInstance().LoadAddonDescriptionFromMemory(xml.RootElement(), addon))
  {
    // set the correct path
    addon->Props().path = items[0]->GetPath();
    addon->Props().icon = URIUtils::AddFileToFolder(items[0]->GetPath(), "icon.png");

    // install the addon
    return DoInstall(addon, RepositoryPtr());
  }

  CEventLog::GetInstance().AddWithNotification(
    EventPtr(new CNotificationEvent(EventLevelError, 24045,
                 StringUtils::Format(g_localizeStrings.Get(24143).c_str(), path.c_str()))), false);
  return false;
}
Пример #15
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;
}
Пример #16
0
bool CAddonInstallJob::DoWork()
{
  SetTitle(StringUtils::Format(g_localizeStrings.Get(24057).c_str(), m_addon->Name().c_str()));
  SetProgress(0);

  // check whether all the dependencies are available or not
  SetText(g_localizeStrings.Get(24058));
  std::pair<std::string, std::string> failedDep;
  if (!CAddonInstaller::GetInstance().CheckDependencies(m_addon, failedDep))
  {
    std::string details = StringUtils::Format(g_localizeStrings.Get(24142).c_str(), failedDep.first.c_str(), failedDep.second.c_str());
    CLog::Log(LOGERROR, "CAddonInstallJob[%s]: %s", m_addon->ID().c_str(), details.c_str());
    ReportInstallError(m_addon->ID(), m_addon->ID(), details);
    return false;
  }

  AddonPtr repoPtr = GetRepoForAddon(m_addon);
  std::string installFrom;
  if (!repoPtr || repoPtr->Props().libname.empty())
  {
    // Addons are installed by downloading the .zip package on the server to the local
    // packages folder, then extracting from the local .zip package into the addons folder
    // Both these functions are achieved by "copying" using the vfs.

    std::string dest = "special://home/addons/packages/";
    std::string package = URIUtils::AddFileToFolder("special://home/addons/packages/",
                                                    URIUtils::GetFileName(m_addon->Path()));
    if (URIUtils::HasSlashAtEnd(m_addon->Path()))
    { // passed in a folder - all we need do is copy it across
      installFrom = m_addon->Path();
    }
    else
    {
      CAddonDatabase db;
      if (!db.Open())
      {
        CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to open database", m_addon->ID().c_str());
        ReportInstallError(m_addon->ID(), m_addon->ID());
        return false;
      }

      std::string md5;
      // check that we don't already have a valid copy
      if (!m_hash.empty() && CFile::Exists(package))
      {
        if (db.GetPackageHash(m_addon->ID(), package, md5) && m_hash != md5)
        {
          db.RemovePackage(package);
          CFile::Delete(package);
        }
      }

      // zip passed in - download + extract
      if (!CFile::Exists(package))
      {
        std::string path(m_addon->Path());
        if (!m_referer.empty() && URIUtils::IsInternetStream(path))
        {
          CURL url(path);
          url.SetProtocolOptions(m_referer);
          path = url.Get();
        }

        if (!DownloadPackage(path, dest))
        {
          CFile::Delete(package);

          CLog::Log(LOGERROR, "CAddonInstallJob[%s]: failed to download %s", m_addon->ID().c_str(), package.c_str());
          ReportInstallError(m_addon->ID(), URIUtils::GetFileName(package));
          return false;
        }
      }

      // at this point we have the package - check that it is valid
      SetText(g_localizeStrings.Get(24077));
      if (!m_hash.empty())
      {
        md5 = CUtil::GetFileMD5(package);
        if (!StringUtils::EqualsNoCase(md5, m_hash))
        {
          CFile::Delete(package);

          CLog::Log(LOGERROR, "CAddonInstallJob[%s]: MD5 mismatch after download %s", m_addon->ID().c_str(), package.c_str());
          ReportInstallError(m_addon->ID(), URIUtils::GetFileName(package));
          return false;
        }

        db.AddPackage(m_addon->ID(), package, md5);
      }

      // check the archive as well - should have just a single folder in the root
      CURL archive = URIUtils::CreateArchivePath("zip", CURL(package), "");

      CFileItemList archivedFiles;
      CDirectory::GetDirectory(archive, archivedFiles);

      if (archivedFiles.Size() != 1 || !archivedFiles[0]->m_bIsFolder)
      {
        // invalid package
        db.RemovePackage(package);
        CFile::Delete(package);

        CLog::Log(LOGERROR, "CAddonInstallJob[%s]: invalid package %s", m_addon->ID().c_str(), package.c_str());
        ReportInstallError(m_addon->ID(), URIUtils::GetFileName(package));
        return false;
      }

      installFrom = archivedFiles[0]->GetPath();
    }
    repoPtr.reset();
  }

  // run any pre-install functions
  ADDON::OnPreInstall(m_addon);

  // perform install
  if (!Install(installFrom, repoPtr))
    return false;

  // run any post-install guff
  CEventLog::GetInstance().Add(
    EventPtr(new CAddonManagementEvent(m_addon, m_update ? 24065 : 24064)),
    !IsModal() && CSettings::GetInstance().GetBool(CSettings::SETTING_GENERAL_ADDONNOTIFICATIONS), false);

  ADDON::OnPostInstall(m_addon, m_update, IsModal());

  //Clear addon from the disabled table
  CAddonDatabase database;
  database.Open();
  database.DisableAddon(m_addon->ID(), false);

  // and we're done!
  MarkFinished();
  return true;
}
Пример #17
0
bool CAddonInstallJob::DoWork()
{
  AddonPtr repoPtr = GetRepoForAddon(m_addon);
  CStdString installFrom;
  if (!repoPtr || repoPtr->Props().libname.empty())
  {
    // Addons are installed by downloading the .zip package on the server to the local
    // packages folder, then extracting from the local .zip package into the addons folder
    // Both these functions are achieved by "copying" using the vfs.

    CStdString dest="special://home/addons/packages/";
    CStdString package = URIUtils::AddFileToFolder("special://home/addons/packages/",
                                                URIUtils::GetFileName(m_addon->Path()));

    if (URIUtils::HasSlashAtEnd(m_addon->Path()))
    { // passed in a folder - all we need do is copy it across
      installFrom = m_addon->Path();
    }
    else
    {
      // zip passed in - download + extract
      CStdString path(m_addon->Path());
      if (!m_referer.empty() && URIUtils::IsInternetStream(path))
      {
        CURL url(path);
        url.SetProtocolOptions(m_referer);
        path = url.Get();
      }
      if (!CFile::Exists(package) && !DownloadPackage(path, dest))
      {
        CFile::Delete(package);
        return false;
      }

      // at this point we have the package - check that it is valid
      if (!CFile::Exists(package) || !CheckHash(package))
      {
        CFile::Delete(package);
        return false;
      }

      // check the archive as well - should have just a single folder in the root
      CStdString archive;
      URIUtils::CreateArchivePath(archive,"zip",package,"");

      CFileItemList archivedFiles;
      CDirectory::GetDirectory(archive, archivedFiles);

      if (archivedFiles.Size() != 1 || !archivedFiles[0]->m_bIsFolder)
      { // invalid package
        CFile::Delete(package);
        return false;
      }
      installFrom = archivedFiles[0]->GetPath();
    }
    repoPtr.reset();
  }

  // run any pre-install functions
  bool reloadAddon = OnPreInstall();

  // perform install
  if (!Install(installFrom, repoPtr))
    return false; // something went wrong

  // run any post-install guff
  OnPostInstall(reloadAddon);

  // and we're done!
  return true;
}
Пример #18
0
bool CAddonInstallJob::DoWork()
{
  AddonPtr repoPtr = GetRepoForAddon(m_addon);
  std::string installFrom;
  if (!repoPtr || repoPtr->Props().libname.empty())
  {
    // Addons are installed by downloading the .zip package on the server to the local
    // packages folder, then extracting from the local .zip package into the addons folder
    // Both these functions are achieved by "copying" using the vfs.

    std::string dest="special://home/addons/packages/";
    std::string package = URIUtils::AddFileToFolder("special://home/addons/packages/",
                                                URIUtils::GetFileName(m_addon->Path()));
    if (URIUtils::HasSlashAtEnd(m_addon->Path()))
    { // passed in a folder - all we need do is copy it across
      installFrom = m_addon->Path();
    }
    else
    {
      std::string     md5;
      CAddonDatabase  db;
      db.Open();

      // check that we don't already have a valid copy
      if (!m_hash.empty() && CFile::Exists(package))
      {
        if (db.GetPackageHash(m_addon->ID(), package, md5) && m_hash != md5)
        {
          db.RemovePackage(package);
          CFile::Delete(package);
        }
      }

      // zip passed in - download + extract
      if (!CFile::Exists(package))
      {
        std::string path(m_addon->Path());
        if (!m_referer.empty() && URIUtils::IsInternetStream(path))
        {
          CURL url(path);
          url.SetProtocolOptions(m_referer);
          path = url.Get();
        }

        if (!DownloadPackage(path, dest))
        {
          CFile::Delete(package);
          return false;
        }
      }

      // at this point we have the package - check that it is valid
      if (!m_hash.empty())
      {
        md5 = CUtil::GetFileMD5(package);
        if (!StringUtils::EqualsNoCase(md5, m_hash))
        {
          CFile::Delete(package);
          ReportInstallError(m_addon->ID(), URIUtils::GetFileName(package));
          CLog::Log(LOGERROR, "MD5 mismatch after download %s", package.c_str());
          return false;
        }
        db.AddPackage(m_addon->ID(), package, md5);
      }

      // check the archive as well - should have just a single folder in the root
      CURL archive = URIUtils::CreateArchivePath("zip",CURL(package),"");

      CFileItemList archivedFiles;
      CDirectory::GetDirectory(archive, archivedFiles);

      if (archivedFiles.Size() != 1 || !archivedFiles[0]->m_bIsFolder)
      { // invalid package
        db.RemovePackage(package);
        CFile::Delete(package);
        return false;
      }
      installFrom = archivedFiles[0]->GetPath();
    }
    repoPtr.reset();
  }

  // run any pre-install functions
  bool reloadAddon = OnPreInstall();

  // perform install
  if (!Install(installFrom, repoPtr))
    return false; // something went wrong

  // run any post-install guff
  OnPostInstall(reloadAddon);

  // and we're done!
  return true;
}